46 Commits

Author SHA1 Message Date
Surya Paolo
2ee710b748 galleria prodotto 2025-08-12 19:43:41 +02:00
Surya Paolo
e3db42dcbc - Iniziato a scrivere la CHATBOT... 2025-08-09 00:48:50 +02:00
Surya Paolo
32210bb96a - corretto sendemail password... l'ho cambiata. e ho messo dei controlli 2025-07-29 12:53:28 +02:00
Surya Paolo
f26ae170bb - Ricerca delle Organizzazioni, per inviare i RIS. 2025-07-21 22:49:55 +02:00
Surya Paolo
a189aeb99c - Poter impostare per ogni Provincia un Circuito RIS specifico, anziché quello provinciale:
Esempio: Napoli: (Circuito RIS Campania) e Sud Sardegna: Cagliari.
2025-07-21 19:08:43 +02:00
Surya Paolo
e118c30f47 - Aggiunta possibilità di disattivare i link alle immagini dei libri. (opzione sul catalogo: disattiva_link_immagini) 2025-07-18 10:43:16 +02:00
Surya Paolo
fb11e15907 - Aggiunta della copertina iniziale nelle raccolte (Catalogo Generale).
- Corretto altezza delle immagini che erano stretchate.
- Fix: poter spostare l'ordinamento dei libri corretto.
2025-07-15 17:46:37 +02:00
Surya Paolo
87c8bf4c45 - corretto import XLS... 2025-07-11 15:03:01 +02:00
Surya Paolo
efd1d12ba7 - Import di un file XLS contenente una lista di libri, all'interno di un catalogo. 2025-07-11 12:55:30 +02:00
Surya Paolo
29437d9d7b . esportazione lista catalogo direttamente in EXCEL, e scelta dei campi. 2025-07-10 00:43:37 +02:00
Surya Paolo
ed27a6f6a5 -statistiche OK 2025-07-08 18:01:24 +02:00
Surya Paolo
d6579763f4 - Aggiunto le Statistiche di visualizzazione delle pagine.
- Aggiunto il componente per visualizzare le statistiche
2025-07-08 16:19:05 +02:00
Surya Paolo
88cb2f13cc - Non funziona l'ammetti il nuovo registrato, sulla App.
- All'interno di una Organizzazione, mostrare se non si è ancora entrati in un Circuito, mettere bottone per Entrare.
2025-07-08 10:25:05 +02:00
Surya Paolo
91ac7a5bde - aggiornato la versione STAMPA, che non funzionava 2025-07-07 09:37:56 +02:00
Surya Paolo
0b06f9f93a - Raccolte Cataloghi corretto e migliorato.
- Bottoni "Apri" e "PDF".
2025-07-06 23:13:03 +02:00
Surya Paolo
a13635ab4e - Sistemato i Referenti (e non Editori), quando crei un nuovo Catalogo ti imposta la proprietà a te, ma chiunque Collaboratore potrebbe cmq modificartelo. 2025-07-01 12:59:54 +02:00
Surya Paolo
31a93424aa - aggiunto filtro nella lista producttable
- ora compare il bottone aggiungi alla lista solo se non è presente.
- corretto la ricerca con "#"
2025-06-25 17:48:44 +02:00
Surya Paolo
8d4158c2c6 - corretto il titolo che lo prendo dall'estrazione del sito... JSON. 2025-06-23 20:48:11 +02:00
Surya Paolo
8c0619992b - Corretta query di estrapolazione libri su GM (Marco)
- aggiornato bestseller su fatlast1Y
- non mostrare piu i libri che non hanno l'immagine (sul catalogo).
- metti online i compressi
2025-06-16 19:36:57 +02:00
Surya Paolo
5668c620da - Sistemato link pdf che ogni volta che si aggiorna prendeva il PDF dalla cache...
- Raccolta Cataloghi, procedura che li AUTO genera in automatico.
2025-06-13 17:46:03 +02:00
Surya Paolo
6b9ddc8986 - Creazione di un Nuovo Catalogo (e la sua relativa pagina), a partire da un modello ed un catalogo esistente.
- Aggiunta dei bottoni sul Ccatalogocard
2025-06-12 23:49:18 +02:00
Surya Paolo
133dc6a502 - aggiornato carrello e bottoni sul catalogo 2025-06-12 10:08:13 +02:00
Surya Paolo
25377090c1 - corretto la gestione degli Sconti
- Duplicare un Catalogo
2025-06-11 01:05:25 +02:00
Surya Paolo
d1d4b73da0 - Esporta Lista Carrello (Totale)
- Sconto Applicato
2025-06-09 09:48:40 +02:00
Surya Paolo
f88f433003 - Aggiunto bottone Aggiungi al Carrello sulla lista dei libri dei cataloghi 2025-06-06 00:07:53 +02:00
Surya Paolo
28a4fe1952 - sistemato "Pare che selezionando una condizione, non sempre viene aggiornato il record !"
- Aggiunto filtro "Escludi Editoriale"
2025-06-04 15:46:39 +02:00
Surya Paolo
f85b8d0637 - Corretto la possibilità di effettuare un Ordine di libri, sul sito gruppomacro.app. arriverà una email a "info@gruppomacro.app". 2025-06-03 01:01:46 +02:00
Surya Paolo
3d6455f23c - generazione della raccolta PDF OK !!! 2025-05-30 16:45:01 +02:00
Surya Paolo
f0c25366db - aggiornato la visualoizzazione per scaricare il PDF e per aprirlo 2025-05-30 10:49:32 +02:00
Surya Paolo
d2aaf78c0e - anche la versione file compressa del PDF ora è ok. 2025-05-29 19:19:40 +02:00
Surya Paolo
40214abe64 - generazione del PDF riscritto totalmente
- ora è possibile generarlo anche da backend
- FIX: corretto la qualità del PDF e la dimensione non esatta in pixel...
2025-05-29 18:23:20 +02:00
Surya Paolo
9efd193124 - versione 1.2.50 2025-05-23 19:02:51 +02:00
Surya Paolo
0e5d28d199 - Finalmente risolto il calcolo e l'impaginazione del PDF, per WEb e per Stampa (300 dpi) !
- corretto altre cose sulla lista cataloghi.
2025-05-23 17:02:41 +02:00
Surya Paolo
d6aaaabb00 - corretto footer catalogo
- corretti il path delle immagini (quando hanno lo spazio nel nomefile).
- aggiunto colore di sfondo per il testo descrittivo, in trasparenza
2025-05-21 12:06:15 +02:00
Surya Paolo
10097f4238 - Per generare la sinossi è possibile estrarre con 1 click la descrizione sia da Amazon che da GruppoMacro.
- corretto piccolo bug sul catalogo.
2025-05-20 12:21:51 +02:00
Surya Paolo
a3c7b92c0c - Estrazione dei dati da Amazon
- Ciclo di Estrapolazione di tutti i prodotti ed aggiornamento dei campi scraped e scraped_updated
- Creazione file CSV con i campi modificati.
2025-05-19 17:33:58 +02:00
Surya Paolo
a374a7d7bc - estrazione dei dati del libro sul sito di Amazon.
- possibilità di visualizzare i dati estratti e di aggiornare i dati, sia solo se vuoti, che sovrascrivere tutti i dati.
2025-05-16 18:52:21 +02:00
Surya Paolo
7e50299854 - ver 1.2.47 :
- corretto errore di modifica scheda
- aggiunto scraping (fase 1)
2025-05-16 10:26:55 +02:00
Surya Paolo
1da0e0f4b5 corretto altre cose (workbox mancante) 2025-05-15 21:41:30 +02:00
Surya Paolo
636136a077 - ho migliorato la grafica della generazione del PDF e PDF Stampa. 2025-05-15 19:18:56 +02:00
Surya Paolo
3521a88395 - ottimizzato il caricamento del sito
- ottimizzato il caricamento del catalogo.
2025-05-15 18:22:43 +02:00
Surya Paolo
768d299881 - sistemato timeout corto
- corretto errori sulla generazione del PDF
- corretto alcune directory
- corretto fs.promise
- corretto CORS !
2025-05-15 14:27:46 +02:00
Surya Paolo
a76d6c9b12 - il catalogo si aggiorna in base alle impostazioni del template anche per la "Stampa" 2025-05-14 20:18:16 +02:00
Surya Paolo
0bf8d3c83c - Assegnazione di linkIdTemplate anche per la "Pagina di Default", in modo che posso da "Templates" cambiare le impostazioni. 2025-05-14 17:04:24 +02:00
Surya Paolo
b2c19801e6 - Generazione della Raccolta dei Cataloghi (web e Stampa), e creazione del PDF Online.
- Lista Raccolta Cataloghi, aggiungi/togli catalogo.
2025-05-14 15:02:21 +02:00
Surya Paolo
ee3846159c - Creazione PDF Temporanei (Generati)
- Assegnazione di questi su PDF OnLine e PDF per Stampa
2025-05-12 18:43:30 +02:00
65 changed files with 16970 additions and 9357 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1,12 +1,12 @@
DATABASE=test_PiuCheBuono
DATABASE=test_FreePlanet
UDB=paofreeplanet
PDB=mypassword@1A
SEND_EMAIL=0
SEND_EMAIL_ORDERS=1
PORT=3000
appTelegram_TEST=["1","17"]
appTelegram=["1","17"]
appTelegram_DEVELOP=["17"]
appTelegram_TEST=["1","13"]
appTelegram=["1","13"]
appTelegram_DEVELOP=["13"]
DOMAIN=mongodb://localhost:27017/
AUTH_MONGODB=0
ENABLE_PUSHNOTIFICATION=1
@@ -29,7 +29,7 @@ GCM_API_KEY=""
PROD=0
PROJECT_DESCR_MAIN='__PROJECTS'
SECRK=Askb38v23jjDFaoskBOWj92axXCQ
TOKEN_LIFE=2h
TOKEN_LIFE=1m
REFRESH_TOKEN_LIFE=14d
FTPSERVER_HOST=139.162.166.31
FTPSERVER_PORT=21
@@ -38,9 +38,4 @@ FTPSERVER_PWD=ftpmypwd@1A_
AUTH_NEW_SITES=123123123
SCRIPTS_DIR=admin_scripts
CLOUDFLARE_TOKENS=[{"label":"Paolo.arena77@gmail.com","value":"M9EM309v8WFquJKpYgZCw-TViM2wX6vB3wlK6GD0"},{"label":"gruppomacro.com","value":"bqmzGShoX7WqOBzkXocoECyBkPq3GfqcM5t6VFd8"}]
MIAB_HOST=box.lamiaposta.org
MIAB_ADMIN_EMAIL=admin@lamiaposta.org
MIAB_ADMIN_PASSWORD=passpao1pabox@1A
DS_API_KEY="sk-222e3addb3d8455d8b0516d93906eec7"
SERVER_A_URL="http://51.77.156.69:3000"
API_KEY_MSSQL="m68yADSr123MIVIDA@154$DSAGVOK"

View File

@@ -80,7 +80,8 @@ p {
/* Whitespace (imageless spacer) */
.whitespace {
line-height: 0; }
line-height: 0;
}
.firma {
font-size: 0.75rem; }

View File

@@ -1 +1,12 @@
<div class="row align-start" style="gap:0px;flex-direction:column;flex:1;display:flex;justify-content:space-between;"><!-- Parte superiore --><div class="justify-start" style="flex-grow:0"><span style="font-size:calc(12 * var(--scalecatalog) * 1px)" class="book-author">{autore}</span><div style="font-size:calc(16 * var(--scalecatalog) * 1px);font-weight:bold;" class="book-title">{titolo}</div><span class="book-descr">{descrizione}</span></div><!-- Parte inferiore (book-details e barcode) --><div style="margin-top:auto;width:100%"><div class="justify-end book-details" style="flex-grow:0;font-size:calc(10 * var(--scalecatalog) * 1px);">Pagine: <b>{pagine}</b><br />Formato: <b>{misure}</b><br />Prezzo: <b>{prezzo} €</b><br /></div></div></div>
<div class="row align-start" style="gap:0px;flex-direction:column;flex:1;display:flex;justify-content:space-between;">
<!-- Parte superiore -->
<div class="justify-start" style="flex-grow:0"><span style="font-size:calc(12 * var(--scalecatalogx) * 1px)"
class="book-author">{autore}</span>
<div style="font-size:calc(16 * var(--scalecatalogx) * 1px);font-weight:bold;" class="book-title">{titolo}</div>
<span class="book-descr">{descrizione}</span>
</div><!-- Parte inferiore (book-details e barcode) -->
<div style="margin-top:auto;width:100%">
<div class="justify-end book-details" style="flex-grow:0;font-size:calc(10 * var(--scalecatalog) * 1px);">
Pagine: <b>{pagine}</b><br />Formato: <b>{misure}</b><br />Prezzo: <b>{prezzo} €</b><br /></div>
</div>
</div>

BIN
emails/.DS_Store vendored

Binary file not shown.

View File

@@ -55,8 +55,7 @@ html
tr
td(class="whitespace", height="10")
p &nbsp;
td
- var totalPrice = orders.totalPrice
- var note = orders.note
@@ -64,6 +63,7 @@ html
each rec in orders.items
- var descr = rec.order.product.productInfo.name
- var code = rec.order.product.productInfo.code
- var img = dirimg + rec.order.product.productInfo.imagefile
- var price = rec.order.price
- var after_price = rec.order.after_price
@@ -104,6 +104,9 @@ html
tr
td(class="sectionContentTitle boldhigh", valign="top")
p #{descr}
tr
td(class="sectionContent", valign="top")
p Codice: #{code}
tr
td(class="sectionContent", valign="top")
p Prezzo: #{price} € #{after_price}

View File

@@ -52,7 +52,7 @@ html
if (miordconfirmed)
p!= miordconfirmed
else
p Puoi pertanto venire a ritirarli direttamente in sede, negli orari che ti sono stati indicati.
p Puoi venire a ritirarli direttamente in sede, negli orari che ti sono stati indicati.
p &nbsp;
@@ -62,6 +62,7 @@ html
each rec in orders.items
- var descr = rec.order.product.productInfo.name
- var code = rec.order.product.productInfo.code
- var img = dirimg + rec.order.product.productInfo.imagefile
- var price = rec.order.product.price
- var after_price = rec.order.product.after_price
@@ -101,6 +102,9 @@ html
tr
td(class="sectionContentTitle boldhigh", valign="top")
p #{descr}
tr
td(class="sectionContent", valign="top")
p Codice: #{code}
tr
td(class="sectionContent", valign="top")
p Prezzo: #{price} € #{after_price}

View File

@@ -156,9 +156,6 @@ html
}
.whitespace {
line-height:0;
font-size:0;
height:20px;
}
@media only screen and (max-width:480px) {

View File

@@ -4,3 +4,5 @@ Dom 02/03 ORE 16:32: USER [surya1977]: ciao
Lun 10/03 ORE 15:52: USER [surya1977]: ciao
Lun 10/03 ORE 15:56: USER [surya1977]: ciao
Lun 07/07 ORE 10:45: USER [surya1977]: ciao

View File

@@ -836,3 +836,5 @@ In attesa di riscontri, salutiamo! 🍚💚
Il gruppo dei Facilitatori Territoriali RISO
Mer 24/04 ORE 22:02: 🤖: Da Sùrya (Paolo) (paoloar77):
✅ la regolarizzazione può avv
Lun 07/07 ORE 10:50: 🤖: Da Sùrya undefined (surya1977):
✅ provatest7 è stato Ammesso correttamente (da surya1977)!

View File

@@ -20,6 +20,8 @@
"bcryptjs": "^3.0.2",
"bluebird": "^3.7.2",
"body-parser": "^1.20.3",
"cheerio": "^1.0.0",
"compress-pdf": "^0.5.3",
"cookie-parser": "^1.4.7",
"cors": "^2.8.5",
"country-codes-list": "^2.0.0",
@@ -56,6 +58,7 @@
"pem": "^1.14.8",
"preview-email": "^3.1.0",
"pug": "^3.0.3",
"puppeteer": "^24.9.0",
"rate-limiter-flexible": "^5.0.5",
"request": "^2.88",
"sanitize-html": "^2.14.0",
@@ -67,6 +70,7 @@
"validator": "^13.12.0",
"vhost": "^3.0.2",
"web-push": "^3.6.7",
"xlsx": "^0.18.5",
"xml2js": "^0.6.2",
"xoauth2": "^1.2.0"
},

View File

@@ -7,10 +7,11 @@ const tools = require('../tools/general');
const axios = require('axios');
const T_Web_Articoli = require('../models/t_web_articoli');
const T_Web_Argomenti = require('../models/t_web_argomenti');
const T_Web_StatiProdotto = require('../models/t_web_statiprodotto');
const T_Web_TipiFormato = require('../models/t_web_tipiformato');
const SERVER_A_URL = process.env.SERVER_A_URL || "";
const SERVER_A_URL = process.env.SERVER_A_URL || '';
const API_KEY = process.env.API_KEY_MSSQL;
const mongoose = require('mongoose').set('debug', false);
@@ -40,15 +41,18 @@ const getArticlesSales = async () => {
ORDER BY totVen DESC;
`;
const response = await axios.post(SERVER_A_URL + '/query', { query }, {
headers: { 'x-api-key': API_KEY }
});
const response = await axios.post(
SERVER_A_URL + '/query',
{ query },
{
headers: { 'x-api-key': API_KEY },
}
);
return response.data || [];
} catch (error) {
console.error("Errore nel recupero degli articoli:", error);
throw new Error("Errore nel recupero degli articoli venduti.");
console.error('Errore nel recupero degli articoli:', error);
throw new Error('Errore nel recupero degli articoli venduti.');
}
};
@@ -56,7 +60,7 @@ const getArticlesSales = async () => {
exports.getArticlesSalesHandler = async (req, res) => {
try {
const data = await getArticlesSales();
if (!data.length) return res.status(404).json({ message: "Nessun articolo trovato." });
if (!data.length) return res.status(404).json({ message: 'Nessun articolo trovato.' });
res.json(data);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -67,10 +71,13 @@ exports.getArticlesSalesHandler = async (req, res) => {
exports.exportArticlesSalesByJSON = async (req, res) => {
try {
const data = await getArticlesSales();
if (!data.length) return res.status(404).json({ message: "Nessun articolo trovato." });
if (!data.length) return res.status(404).json({ message: 'Nessun articolo trovato.' });
res.setHeader("Content-Type", "application/json");
res.setHeader("Content-Disposition", `attachment; filename="ranking_articles_${new Date().toISOString().split('T')[0]}.json"`);
res.setHeader('Content-Type', 'application/json');
res.setHeader(
'Content-Disposition',
`attachment; filename="ranking_articles_${new Date().toISOString().split('T')[0]}.json"`
);
res.json(data);
} catch (error) {
res.status(500).json({ error: error.message });
@@ -81,19 +88,18 @@ exports.getTableContent = async (options) => {
try {
// Chiama getTableContent, se ritorna errore hangup, allora attendi 2 secondi e poi richiamala.
const tableContent = await this.getTableContentBase(options);
console.log(' uscito dalla funzione getTableContentBase ... ')
console.log(' uscito dalla funzione getTableContentBase ... ');
return tableContent;
} catch (error) {
console.error('Error: ', error?.message);
if (error.message === 'socket hang up') {
console.log('Error: hangup, waiting 2 seconds and retrying...');
await new Promise(resolve => setTimeout(resolve, 2000));
await new Promise((resolve) => setTimeout(resolve, 2000));
return await this.getTableContent(options);
}
}
};
exports.formatDate = (dateValue) => {
const date = new Date(dateValue);
const day = String(date.getDate()).padStart(2, '0');
@@ -113,61 +119,66 @@ exports.getModelByNameTable = (nameTable) => {
default:
return null;
}
}
};
exports.getTableContentBase = async (options) => {
try {
const myurl = SERVER_A_URL + '/query';
console.log('getTableContentBase...', myurl)
console.log('getTableContentBase...', myurl);
// Verifica se la tabella esiste
const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
const checkResponse = await axios.post(myurl, { query: checkTableQuery }, {
headers: { 'x-api-key': API_KEY }
});
console.log(' risposta 1...')
const checkResponse = await axios.post(
myurl,
{ query: checkTableQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
console.log(' risposta 1...');
if (!checkResponse?.data || checkResponse?.data.length === 0 || checkResponse?.data[0].tableExists === 0) {
return `La tabella '${options.nameTable}' non esiste.`;
}
// Recupera le colonne della tabella principale dal catalogo
const columnsQuery = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${options.nameTable}'`;
const columnsResponse = await axios.post(SERVER_A_URL + '/query', { query: columnsQuery }, {
headers: { 'x-api-key': API_KEY }
});
console.log(' risposta 2 (schema)...')
const tableColumns = columnsResponse.data.map(col => col.COLUMN_NAME);
const columnsResponse = await axios.post(
SERVER_A_URL + '/query',
{ query: columnsQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
console.log(' risposta 2 (schema)...');
const tableColumns = columnsResponse.data.map((col) => col.COLUMN_NAME);
// Mappatura per unire i campi (ID e Descrizione)
const mergedMapping = {
"IdStatoProdotto": "DescrizioneStatoProdotto",
"IdTipologia": "DescrizioneTipologia",
"IdTipoFormato": "DescrizioneFormato",
"IdCollana": "DescrizioneCollana",
"ListaArgomenti": "DescrArgomento",
"ListaAutori": "AutoriCompleti",
"IdMarchioEditoriale": "CasaEditrice",
IdStatoProdotto: 'DescrizioneStatoProdotto',
IdTipologia: 'DescrizioneTipologia',
IdTipoFormato: 'DescrizioneFormato',
IdCollana: 'DescrizioneCollana',
ListaArgomenti: 'DescrArgomento',
ListaAutori: 'AutoriCompleti',
IdMarchioEditoriale: 'CasaEditrice',
};
// Costruisce la query per recuperare i record
let dataQuery = "";
let dataQuery = '';
let records = [];
if (options?.usaDBGMLocale) {
// Cerca il modello corrispondente alla tabella se esiste
let mymodel = this.getModelByNameTable(options.nameTable);
if (!mymodel) {
// fai una query sul db locale mongodb dela tabella chiamata "options.nameTable"
mymodel = mongoose.model(options.nameTable, new mongoose.Schema({}, { strict: false }));
if (!mymodel)
return `Il modello per la tabella '${options.nameTable}' non esiste.`;
if (!mymodel) return `Il modello per la tabella '${options.nameTable}' non esiste.`;
}
if (options.aggregation) {
console.log('options.aggregation', options.aggregation);
records = await mymodel.aggregate(options.aggregation);
} else {
const pipeline = [];
@@ -195,9 +206,7 @@ exports.getTableContentBase = async (options) => {
}
console.log('results', records ? records[0] : ' non ricevuto');
} else {
let columnsToShow = 'T.*';
if (options.fieldGM) {
columnsToShow = 'T.' + options.fieldGM;
@@ -205,44 +214,67 @@ exports.getTableContentBase = async (options) => {
if (options.nameTable.toLowerCase() === 't_web_articoli') {
if (true) {
dataQuery = `
dataQuery =
`
SELECT TOP ${options.numrec || 10000}
${columnsToShow}
` + (options.campispeciali ? `
,f.DescrizioneStatoProdotto
` +
(options.campispeciali
? `
,i.DescrizioneTipologia
,f.DescrizioneStatoProdotto
,n.DescrizioneFormato
,y.DescrizioneCollana
,z.AutoriCompleti
,i2.DescrArgomento
,z3.CasaEditrice` : ``) + (options.showQtaDisponibile ? ` ,q.QtaDisponibile ` : ``) +
` FROM T_WEB_Articoli T
JOIN(
,z3.CasaEditrice`
: ``) +
(options.showQtaDisponibile ? ` ,q.QtaDisponibile ` : ``) +
` FROM T_WEB_Articoli T WITH (noLock)
RIGHT JOIN(
SELECT IdArticolo, MAX(DataOra) AS data
FROM T_WEB_Articoli
GROUP BY IdArticolo
) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data `
+ (options.campispeciali ?
` LEFT JOIN(
SELECT e.IdStatoProdotto, e.Descrizione as DescrizioneStatoProdotto
FROM T_WEB_StatiProdotto e
JOIN(
SELECT IdStatoProdotto, MAX(DataOra) as data1
FROM T_WEB_StatiProdotto
GROUP BY IdStatoProdotto
) c ON e.IdStatoProdotto = c.IdStatoProdotto AND e.DataOra = c.data1
) f ON T.IdStatoProdotto = f.IdStatoProdotto
LEFT JOIN(
SELECT g.IdTipologia, g.Descrizione as DescrizioneTipologia
FROM T_WEB_Tipologie g
) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data ` +
(options.campispeciali
? `
RIGHT JOIN
( SELECT
e.IdStatoProdotto,
e.Descrizione as DescrizioneStatoProdotto
FROM
T_WEB_StatiProdotto e
JOIN
(
SELECT
IdStatoProdotto,
MAX(DataOra) as data1
FROM
T_WEB_StatiProdotto
GROUP BY
IdStatoProdotto ) c
ON
e.IdStatoProdotto = c.IdStatoProdotto
AND e.DataOra = c.data1 ) f
ON
T.IdStatoProdotto = f.IdStatoProdotto
RIGHT JOIN(
SELECT g.IdTipologia,
g.Descrizione as DescrizioneTipologia
FROM
T_WEB_Tipologie g
JOIN(
SELECT IdTipologia, MAX(DataOra) as data1
FROM T_WEB_Tipologie
FROM
T_WEB_Tipologie
GROUP BY IdTipologia
) h ON g.IdTipologia = h.IdTipologia AND g.DataOra = h.data1
) i ON T.IdTipologia = i.IdTipologia
LEFT JOIN(
SELECT l.IdTipoFormato, l.Descrizione as DescrizioneFormato
) i ON
T.IdTipologia = i.IdTipologia
RIGHT JOIN(
SELECT l.IdTipoFormato,
l.Descrizione as DescrizioneFormato
FROM T_WEB_TipiFormato l
JOIN(
SELECT IdTipoFormato, MAX(DataOra) as data1
@@ -250,16 +282,18 @@ exports.getTableContentBase = async (options) => {
GROUP BY IdTipoFormato
) m ON l.IdTipoFormato = m.IdTipoFormato AND l.DataOra = m.data1
) n ON T.IdTipoFormato = n.IdTipoFormato
LEFT JOIN(
SELECT v.IdCollana, v.Descrizione as DescrizioneCollana
RIGHT JOIN(
SELECT v.IdCollana,
v.Descrizione as DescrizioneCollana
FROM T_WEB_Collane v
INNER JOIN(
SELECT IdCollana, MAX(ID) as MaxID
SELECT IdCollana,
MAX(ID) as MaxID
FROM T_WEB_Collane
GROUP BY IdCollana
) x ON v.IdCollana = x.IdCollana AND v.ID = x.MaxID
) y ON T.IdCollana = y.IdCollana
LEFT JOIN(
RIGHT JOIN(
SELECT g2.IdArgomento, g2.Descrizione as DescrArgomento
FROM T_WEB_Argomenti g2
INNER JOIN(
@@ -268,7 +302,30 @@ exports.getTableContentBase = async (options) => {
GROUP BY IdArgomento
) h ON g2.IdArgomento = h.IdArgomento AND g2.DataOra = h.data12
) i2 ON T.ListaArgomenti = i2.IdArgomento
LEFT JOIN(
`+
(options.showQtaDisponibile
? ` RIGHT JOIN(
SELECT o.Codice, o.QtaDisponibile
FROM T_WEB_Disponibile o
JOIN(
SELECT Codice, MAX(DataOra) as data1
FROM T_WEB_Disponibile
GROUP BY Codice
) p ON o.Codice = p.Codice AND o.DataOra = p.data1
) q ON T.IdArticolo = q.Codice`
: ``) +
` RIGHT JOIN(
SELECT a3.IdMarchioEditoriale, a3.Descrizione as CasaEditrice
FROM T_WEB_MarchiEditoriali a3
JOIN(
SELECT IdMarchioEditoriale, MAX(DataOra) as maxData
FROM T_WEB_MarchiEditoriali
GROUP BY IdMarchioEditoriale
) aa3 ON a3.IdMarchioEditoriale = aa3.IdMarchioEditoriale AND a3.DataOra = aa3.maxData
) z3 ON T.IdMarchioEditoriale = z3.IdMarchioEditoriale
RIGHT JOIN(
SELECT
T1.IdArticolo,
STUFF((
@@ -283,7 +340,7 @@ exports.getTableContentBase = async (options) => {
JOIN(
SELECT a.IdAutore, CONCAT(a.Nome, ' ', a.Cognome) AS AutoreCompleto
FROM T_WEB_Autori a
JOIN(
RIGHT JOIN(
SELECT IdAutore, MAX(DataOra) AS maxData
FROM T_WEB_Autori
GROUP BY IdAutore
@@ -292,28 +349,11 @@ exports.getTableContentBase = async (options) => {
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS AutoriCompleti
FROM T_WEB_Articoli T1
GROUP BY T1.IdArticolo, T1.ListaAutori
) z ON T.IdArticolo = z.IdArticolo
LEFT JOIN(
SELECT a3.IdMarchioEditoriale, a3.Descrizione as CasaEditrice
FROM T_WEB_MarchiEditoriali a3
JOIN(
SELECT IdMarchioEditoriale, MAX(DataOra) as maxData
FROM T_WEB_MarchiEditoriali
GROUP BY IdMarchioEditoriale
) aa3 ON a3.IdMarchioEditoriale = aa3.IdMarchioEditoriale AND a3.DataOra = aa3.maxData
) z3 ON T.IdMarchioEditoriale = z3.IdMarchioEditoriale `
: ``)
+ (options.showQtaDisponibile ?
` LEFT JOIN(
SELECT o.Codice, o.QtaDisponibile
FROM T_WEB_Disponibile o
JOIN(
SELECT Codice, MAX(DataOra) as data1
FROM T_WEB_Disponibile
GROUP BY Codice
) p ON o.Codice = p.Codice AND o.DataOra = p.data1
) q ON T.IdArticolo = q.Codice` : ``)
WHERE t1.DataOra = (select max(DataOra) AS DataOra from T_web_articoli As h WHERE h.IdArticolo = T1.IdArticolo)
GROUP BY T1.IdArticolo, T1.ListaAutori ) z ON T.IdArticolo = z.IdArticolo
`
: ``);
} else {
dataQuery += `
SELECT TOP ${options.numrec}
@@ -329,7 +369,7 @@ exports.getTableContentBase = async (options) => {
} else {
dataQuery = `SELECT TOP ${options.numrec || 10000} * FROM ${options.nameTable} `;
}
if (options.where && options.where.trim() !== "") {
if (options.where && options.where.trim() !== '') {
dataQuery += ` WHERE ${options.where} `;
}
@@ -337,9 +377,13 @@ exports.getTableContentBase = async (options) => {
// Esegue la query per recuperare i dati
// console.log('dataQuery', dataQuery);
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
headers: { 'x-api-key': API_KEY }
});
const dataResponse = await axios.post(
SERVER_A_URL + '/query',
{ query: dataQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
records = dataResponse?.data;
}
@@ -353,7 +397,7 @@ exports.getTableContentBase = async (options) => {
let displayColumns;
if (options.nameTable.toLowerCase() === 't_web_articoli') {
// Usa tutte le proprietà del record, escludendo le colonne dei campi uniti (quelle usate per il merge)
displayColumns = Object.keys(records[0]).filter(col => !Object.values(mergedMapping).includes(col));
displayColumns = Object.keys(records[0]).filter((col) => !Object.values(mergedMapping).includes(col));
} else {
displayColumns = tableColumns;
}
@@ -362,11 +406,12 @@ exports.getTableContentBase = async (options) => {
const getDisplayValue = (record, col) => {
let value = record[col] ?? 'NULL';
// Format date solo se il nome della colonna indica una data/ora
if ((col.toLowerCase().includes("data") || col.toLowerCase().includes("ora")) && value !== 'NULL') {
if ((col.toLowerCase().includes('data') || col.toLowerCase().includes('ora')) && value !== 'NULL') {
if (value.includes(',')) {
// Se ci sono più valori separati da virgola, formatta ciascuno se è una data valida
value = value.split(',')
.map(item => {
value = value
.split(',')
.map((item) => {
const trimmed = item.trim();
const parsed = Date.parse(trimmed);
return !isNaN(parsed) ? this.formatDate(trimmed) : trimmed;
@@ -386,7 +431,7 @@ exports.getTableContentBase = async (options) => {
};
// Costruisce l'output HTML
let output = "";
let output = '';
if (options.outhtml) {
if (records.length === 1) {
// Se c'è un solo record, visualizza una lista di chiavi e valori
@@ -401,7 +446,7 @@ exports.getTableContentBase = async (options) => {
</thead>
<tbody>
`;
displayColumns.forEach(column => {
displayColumns.forEach((column) => {
output += `
<tr>
<td style="padding: 8px;">${column}</td>
@@ -416,18 +461,18 @@ exports.getTableContentBase = async (options) => {
} else {
// Se ci sono più record, visualizza una tabella con intestazioni
output += "<table border='1' style='border-collapse: collapse; width: 100%;'><thead><tr>";
displayColumns.forEach(column => {
displayColumns.forEach((column) => {
output += `< th style = "padding: 8px; background-color: #f2f2f2;" > ${column}</th > `;
});
output += "</tr></thead><tbody>";
records.forEach(record => {
output += "<tr>";
displayColumns.forEach(column => {
output += '</tr></thead><tbody>';
records.forEach((record) => {
output += '<tr>';
displayColumns.forEach((column) => {
output += `< td style = "padding: 8px;" > ${getDisplayValue(record, column)}</td > `;
});
output += "</tr>";
output += '</tr>';
});
output += "</tbody></table>";
output += '</tbody></table>';
}
} else {
// solo dati
@@ -439,14 +484,13 @@ exports.getTableContentBase = async (options) => {
}
} else {
output = [];
records.forEach(record => {
let myrec = {}
records.forEach((record) => {
let myrec = {};
if (options.recordraw) {
myrec = record;
} else {
displayColumns.forEach(column => {
displayColumns.forEach((column) => {
const value = record[column];
if (value !== undefined && value !== null) {
const type = typeof value;
@@ -462,15 +506,17 @@ exports.getTableContentBase = async (options) => {
}
});
}
output.push(myrec)
output.push(myrec);
});
}
}
return output;
} catch (error) {
output = `${error?.response?.data?.error || error?.stack || error.message}`;
console.error("Errore nel recupero della tabella: ", `${error.response.data.error || error.stack || error.message}`);
console.error(
'Errore nel recupero della tabella: ',
`${error.response.data.error || error.stack || error.message}`
);
if (options.outhtml) {
output = `
@@ -511,7 +557,9 @@ exports.getTableContentBase = async (options) => {
</head>
<body>
<div class="error-container">
<div class="error-title">Errore nel Recupero della Tabella ${options.nameTable} con query: ${options.where}</div>
<div class="error-title">Errore nel Recupero della Tabella ${options.nameTable} con query: ${
options.where
}</div>
<div class="error-message">
${error.response.data.error || error.stack || error.message}
</div>
@@ -528,36 +576,39 @@ const setTableContent = async (options) => {
try {
// checkPermissions()
const esegui = true
const esegui = true;
if (esegui) {
// Verifica se la tabella esiste
const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
const checkResponse = await axios.post(SERVER_A_URL + '/query', { query: checkTableQuery }, {
headers: { 'x-api-key': API_KEY }
});
const checkResponse = await axios.post(
SERVER_A_URL + '/query',
{ query: checkTableQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
if (!checkResponse.data || checkResponse.data.length === 0 || checkResponse.data[0].tableExists === 0) {
return `La tabella '${options.nameTable}' non esiste.`;
}
// Costruisce la query per inserire o aggiornare i record
let dataQuery = "";
let dataQuery = '';
if (options.insertMode) {
// Modalità INSERT
const columns = Object.keys(options.data);
const values = columns.map(col => `'${options.data[col]}'`).join(", ");
const values = columns.map((col) => `'${options.data[col]}'`).join(', ');
dataQuery = `
INSERT INTO ${options.nameTable} (${columns.join(", ")})
INSERT INTO ${options.nameTable} (${columns.join(', ')})
VALUES (${values});
`;
} else {
// Modalità UPDATE
const updateFields = Object.keys(options.data)
.map(col => `${col} = '${options.data[col]}'`)
.join(", ");
const whereClause = options.where ? `WHERE ${options.where}` : "";
.map((col) => `${col} = '${options.data[col]}'`)
.join(', ');
const whereClause = options.where ? `WHERE ${options.where}` : '';
dataQuery = `
UPDATE ${options.nameTable}
SET ${updateFields}
@@ -568,9 +619,13 @@ const setTableContent = async (options) => {
console.log('dataQuery', dataQuery);
// Esegue la query per inserire o aggiornare i dati
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
headers: { 'x-api-key': API_KEY }
});
const dataResponse = await axios.post(
SERVER_A_URL + '/query',
{ query: dataQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
if (dataResponse.data && dataResponse.data.affectedRows > 0) {
return `Operazione completata con successo su '${options.nameTable}'.`;
@@ -619,7 +674,9 @@ const setTableContent = async (options) => {
</head>
<body>
<div class="error-container">
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</div>
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${
options.nameTable
}</div>
<div class="error-message">
${error.response.data.error || error.stack || error.message}
</div>
@@ -653,9 +710,13 @@ const checkPermissions = async (options) => {
console.log('checkPermissions query:', dataQuery);
// Esegue la query per inserire o aggiornare i dati
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
headers: { 'x-api-key': API_KEY }
});
const dataResponse = await axios.post(
SERVER_A_URL + '/query',
{ query: dataQuery },
{
headers: { 'x-api-key': API_KEY },
}
);
console.log('checkPermissions result:', dataResponse.data);
@@ -665,7 +726,7 @@ const checkPermissions = async (options) => {
return `Nessun permesso.`;
}
} catch (error) {
console.error("Errore nel check dei Permessi: ", error.message);
console.error('Errore nel check dei Permessi: ', error.message);
if (options.outhtml) {
output = `
<head>
@@ -705,7 +766,9 @@ const checkPermissions = async (options) => {
</head>
<body>
<div class="error-container">
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</div>
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${
options.nameTable
}</div>
<div class="error-message">
${error.response.data.error || error.stack || error.message}
</div>
@@ -733,19 +796,18 @@ exports.viewTable = async (req, res) => {
<div class="row justify-center">
${tableContent}
</div>
`
`;
} else {
out = tableContent;
}
if (tableContent && tableContent.length > 0) {
if (options.updatelocaldb) {
this.updateLocalDb(tableContent[0], options)
this.updateLocalDb(tableContent[0], options);
}
}
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
} catch (error) {
console.error('Error: ', error);
return res.send({ code: server_constants.RIS_CODE_ERR, error });
@@ -754,7 +816,6 @@ exports.viewTable = async (req, res) => {
exports.updateLocalDb = async (tableContent, options) => {
try {
const ProductInfo = require('../models/productInfo');
const CatProd = require('../models/catprod');
@@ -766,11 +827,9 @@ exports.updateLocalDb = async (tableContent, options) => {
const recfound = await ProductInfo.findOne({ code: recproductInfo.code }).lean();
if (recfound) {
ListaArgomenti = tableContent.ListaArgomenti;
let arrayPulito = ListaArgomenti
.trim() // Rimuove gli spazi all'inizio e alla fine
let arrayPulito = ListaArgomenti.trim() // Rimuove gli spazi all'inizio e alla fine
.replace(/[\(\)]/g, '') // Rimuove le parentesi tonde
.split(','); // Divide la stringa in un array usando la virgola come separatore
@@ -780,7 +839,7 @@ exports.updateLocalDb = async (tableContent, options) => {
let reccatprods = [];
for (let i = 0; i < arrayPulito.length; i++) {
const idArgomento = parseInt(arrayPulito[i]);
reccateg = await CatProd.findOne({ idArgomento }).lean();
reccateg = await CatProd.findOne({ idArgomento });
if (reccateg) {
// aggiungi solo se non esiste già
@@ -788,6 +847,13 @@ exports.updateLocalDb = async (tableContent, options) => {
reccatprods.push(reccateg._id);
}
}
if (!reccateg?.idArgomento) {
// Se non c'è l'argomento, allora lo cerco nel DB
const recarg = await T_Web_Argomenti.findOne({ Descrizione: reccateg.name }).lean();
reccateg.idArgomento = recarg.IdArgomento;
await reccateg.save();
}
}
// ora controlla se l'array reccatprods e' diverso da precCatProds
@@ -816,17 +882,20 @@ exports.updateLocalDb = async (tableContent, options) => {
}
if (aggiorna) {
risrecUpdated = await ProductInfo.findOneAndUpdate({ code: recproductInfo.code }, { $set: recproductInfo }, { new: true, upsert: true });
risrecUpdated = await ProductInfo.findOneAndUpdate(
{ code: recproductInfo.code },
{ $set: recproductInfo },
{ new: true, upsert: true }
);
}
return risrecUpdated;
}
} catch (e) {
console.error('Error: ', e);
return null;
}
}
};
// Endpoint per mostrare i dati della tabella
exports.queryTable = async (req, res) => {
@@ -841,13 +910,12 @@ exports.queryTable = async (req, res) => {
<h2>Tabella: ${options.nameTable}</h2>
<div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
${tableContent}
`
`;
} else {
out = tableContent;
}
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
} catch (error) {
console.error('Error: ', error);
return res.send({ code: server_constants.RIS_CODE_ERR, error });
@@ -868,13 +936,12 @@ exports.saveTable = async (req, res) => {
<div class="row justify-center">
${tableContent}
</div>
`
`;
} else {
out = tableContent;
}
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
} catch (error) {
console.error('Error: ', error);
return res.send({ code: server_constants.RIS_CODE_ERR, error });
@@ -895,6 +962,7 @@ exports.mssqlmigrateTables = async (req) => {
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' });
@@ -919,22 +987,18 @@ exports.mssqlmigrateTables = async (req) => {
const migrator = new MssqlMigrator();
return await migrator.migrateTables(listaTabelle);
} catch (e) {
console.error(e.message);
return 'Errore: ' + e.message
return 'Errore: ' + e.message;
}
};
exports.updateAllBook = async (idapp, options) => {
const Macro = require('../modules/Macro'); // Importa la classe Macro
try {
const macro = new Macro(idapp); // Crea un'istanza della classe Macro
options.idapp = idapp;
return await macro.updateLocalDbFromGM_T_Web_Articoli(options);
} catch (e) {
console.error(e.message);
return e.message;
@@ -942,18 +1006,16 @@ exports.updateAllBook = async (idapp, options) => {
};
exports.updateAllBookRoute = async (req, res) => {
try {
const idapp = req.body.idapp;
const options = req.body.options;
const result = await this.updateAllBook(idapp, options);
return res.status(200).send({ data: result });
} catch (e) {
console.error(e.message);
if (res) {
return res.status(400).send(e);
}
}
}
};

View File

@@ -21,6 +21,7 @@ const authenticateMiddleware = async (req, res, next, withUser = false, lean = f
req.user = null;
req.token = null;
req.code = server_constants.RIS_CODE_HTTP_INVALID_TOKEN;
if (!noError)
console.log(` ## ${logPrefix}_TOKEN INVALIDO ❌ ...`);
return noError ? next() : res.status(req.code).send();
}

27
src/server/models/PageView.js Executable file
View File

@@ -0,0 +1,27 @@
// /backend/models/PageView.js
const mongoose = require('mongoose');
const PageViewSchema = new mongoose.Schema({
url: {
type: String,
required: true
},
idapp: String,
ip: {
type: String,
default: 'unknown'
},
userId: String,
username: String,
userAgent: {
type: String
},
referrer: String,
timestamp: {
type: Date,
default: Date.now
}
});
module.exports = mongoose.model('PageView', PageViewSchema);

View File

@@ -1,14 +1,14 @@
mongoose = require('mongoose').set('debug', false)
mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
mongoose.level = 'F';
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const AuthorSchema = new Schema({
@@ -29,13 +29,13 @@ const AuthorSchema = new Schema({
},
});
var Author = module.exports = mongoose.model('Author', AuthorSchema);
var Author = (module.exports = mongoose.model('Author', AuthorSchema));
module.exports.getFieldsForSearch = function () {
return [
{ field: 'name', type: tools.FieldType.string },
{ field: 'surname', type: tools.FieldType.string },
]
];
};
module.exports.executeQueryTable = function (idapp, params) {
@@ -46,10 +46,12 @@ module.exports.executeQueryTable = function (idapp, params) {
module.exports.findAllIdApp = async function (idapp) {
const myfind = { idapp };
return await Author.find(myfind).sort({name: 1, surname: 1});
return await Author.find(myfind).sort({ name: 1, surname: 1 }).select({ idapp: 0 }).lean();
};
module.exports.createIndexes()
module.exports
.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});

View File

@@ -2,14 +2,13 @@ const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
mongoose.level = "F";
mongoose.level = 'F';
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const CartSchema = new Schema({
idapp: {
type: String,
@@ -18,18 +17,25 @@ const CartSchema = new Schema({
totalQty: { type: Number, default: 0 },
totalPrice: { type: Number, default: 0 },
totalPriceCalc: { type: Number, default: 0 },
totalPriceIntero: { type: Number, default: 0 },
department: {
type: String, ref: 'Department',
type: String,
ref: 'Department',
},
items: [
{
order:
{ type: Schema.Types.ObjectId, ref: 'Order' },
order: { type: Schema.Types.ObjectId, ref: 'Order' },
},
],
note: {
type: String,
},
codice_sconto: {
type: String,
},
descr_sconto: {
type: String,
},
note_ordine_gas: {
type: String,
},
@@ -38,7 +44,7 @@ const CartSchema = new Schema({
},
});
var Cart = module.exports = mongoose.model('Cart', CartSchema);
var Cart = (module.exports = mongoose.model('Cart', CartSchema));
module.exports.findAllIdApp = async function (idapp, userId) {
const myfind = { idapp, userId };
@@ -48,47 +54,76 @@ module.exports.findAllIdApp = async function (idapp, userId) {
module.exports.getCartByUserId = async function (uid, idapp) {
try {
const mycart = await getCart(uid, idapp);
if (!mycart) return null;
await updateOrderDetails(mycart.items);
filterValidItems(mycart);
return mycart;
} catch (e) {
console.log('getCartByUserId err', e);
}
};
module.exports.getCartCompletoByCartId = async function (id_cart, idapp) {
try {
const mycart = await getCartById(id_cart, idapp);
if (!mycart) return null;
await updateOrderDetails(mycart.items);
filterValidItems(mycart);
return mycart;
} catch (e) {
console.log('getCartByUserId err', e);
}
};
// Recupera il carrello per l'utente e l'app
async function getCart(uid, idapp) {
const query = { userId: uid, idapp };
return await Cart.findOne(query).lean();
}
async function getCartById(id_cart, idapp) {
return await Cart.findOne({_id: id_cart}).lean();
}
// Aggiorna i dettagli dell'ordine per ogni articolo nel carrello
async function updateOrderDetails(items) {
const Order = require('../models/order');
let query = { userId: uid, idapp };
const mycart = await Cart.findOne(query).lean();
if (!!mycart) {
for (const idkey in mycart.items) {
for (const item of items) {
try {
let idorder = mycart.items[idkey]._id.toString();
let myorder = mycart.items[idkey].order;
if (!!myorder) {
idorder = mycart.items[idkey].order._id.toString();
}
if (idorder) {
let myord = await Order.getTotalOrderById(idorder);
const idorder = item.order ? item.order._id.toString() : item._id.toString();
const myord = await Order.getTotalOrderById(idorder);
if (myord.length > 0) {
mycart.items[idkey].order = myord[0];
}
item.order = myord[0];
}
} catch (e) {
console.log('err', e);
}
}
}
mycart.newitems = []
// Filtra solo gli articoli validi (con quantità > 0 o pre-ordinati)
function filterValidItems(mycart) {
mycart.newitems = [];
for (let item of mycart.items) {
if (item.order && item.order.hasOwnProperty('idapp') && (item.order.quantity > 0 || item.order.quantitypreordered > 0))
mycart.newitems.push(item)
if (
item.order &&
item.order.hasOwnProperty('idapp') &&
(item.order.quantity > 0 || item.order.quantitypreordered > 0)
) {
mycart.newitems.push(item);
}
mycart.items = [...mycart.newitems]
mycart.newitems = []
return mycart;
}
return null;
} catch (e) {
console.log('getCartByUserId err', e);
mycart.items = [...mycart.newitems];
mycart.newitems = [];
}
};
module.exports.updateCartByUserId = async function (userId, newCart) {
const query = { userId: userId };
@@ -105,6 +140,7 @@ module.exports.updateCartByUserId = async function (userId, newCart) {
items: newCart.items,
totalQty: newCart.totalQty,
totalPrice: newCart.totalPrice,
totalPriceIntero: newCart.totalPriceIntero,
totalPriceCalc: newCart.totalPriceCalc,
userId: userId,
},
@@ -116,6 +152,7 @@ module.exports.updateCartByUserId = async function (userId, newCart) {
} else {
// Se il carrello non esiste, crea un nuovo documento
const createdCart = new Cart(newCart);
await createdCart.init();
const savedCart = await createdCart.save();
return savedCart; // Restituisce il carrello creato
}
@@ -132,28 +169,40 @@ module.exports.updateCartByCartId = async function (cartId, newCart) {
const totalQty = newCart.totalQty;
const totalPrice = newCart.totalPrice;
const totalPriceCalc = newCart.totalPriceCalc;
const totalPriceIntero = newCart.totalPriceIntero;
const note = newCart.note;
const codice_sconto = newCart.codice_sconto;
const descr_sconto = newCart.descr_sconto;
const note_ordine_gas = newCart.note_ordine_gas;
const modify_at = new Date();
return await Cart.findOneAndUpdate({ _id: cartId }, {
return await Cart.findOneAndUpdate(
{ _id: cartId },
{
$set: {
items,
totalPrice,
totalPriceCalc,
totalPriceIntero,
totalQty,
note,
codice_sconto,
descr_sconto,
note_ordine_gas,
modify_at: new Date(),
},
}, { new: false }).lean().then((ris) => {
},
{ new: false }
)
.lean()
.then((ris) => {
return ris;
}).catch(err => {
})
.catch((err) => {
console.log('err', err);
return null;
});
};
module.exports.deleteCartByCartId = async function (cartId) {
@@ -164,8 +213,8 @@ module.exports.createCart = async function (newCart) {
return await newCart.save();
};
Cart.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});

View File

@@ -1,4 +1,4 @@
const mongoose = require('mongoose').set('debug', false)
const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
const tools = require('../tools/general');
@@ -7,15 +7,13 @@ const { ObjectId } = require('mongodb');
const { IImg } = require('../models/myscheda');
mongoose.Promise = global.Promise;
mongoose.level = "F";
mongoose.level = 'F';
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const CatalogSchema = new Schema({
idapp: {
type: String,
@@ -30,22 +28,29 @@ const CatalogSchema = new Schema({
},
foto_collana: IImg,
idCollane: [{
idCollane: [
{
type: String,
}],
idTipoFormato: [{
},
],
idTipoFormato: [
{
type: Number,
}],
},
],
argomenti: [{
argomenti: [
{
type: String,
}],
},
],
condition_andor: {
type: Number,
default: 0,
},
editore: [{ type: String }],
editore_escludi: [{ type: String }],
descr_introduttiva: {
type: String,
@@ -53,12 +58,13 @@ const CatalogSchema = new Schema({
idPageAssigned: {
type: String,
},
idPageAssigned_stampa: {
referenti: [
{
type: String,
},
referenti: [{
type: String,
}],
],
disattiva_link_immagini: Boolean,
img_bordata: IImg,
img_intro: IImg,
@@ -67,9 +73,16 @@ const CatalogSchema = new Schema({
pagina_introduttiva_sfondo_nero: {
type: Boolean,
},
backcolor: String,
pdf_generato: String,
pdf_generato_compressed: String,
pdf_generato_size: String,
pdf_generato_compr_size: String,
pdf_generato_stampa: String,
pdf_generato_stampa_compressed: String,
pdf_generato_stampa_compr_size: String,
pdf_generato_stampa_size: String,
data_generato: {
type: Date,
},
@@ -82,22 +95,36 @@ const CatalogSchema = new Schema({
data_lista_generata: {
type: Date,
},
data_lista_updated: {
type: Date,
},
username_lista_updated: {
type: String,
},
pdf_online: String,
pdf_online_size: String,
data_online: {
type: Date,
},
pdf_online_stampa: String,
pdf_online_stampa_size: String,
data_online_stampa: {
type: Date,
},
date_created: {
type: Date,
default: Date.now
default: Date.now,
},
date_updated: {
type: Date,
},
lista_prodotti: [{
lista_prodotti: [
{
type: Schema.Types.ObjectId,
ref: 'Product',
}],
},
],
isCatalogoGenerale: Boolean,
});
@@ -113,7 +140,7 @@ CatalogSchema.pre('save', async function (next) {
*/
CatalogSchema.statics.getFieldsForSearch = function () {
return [{ field: 'title', type: tools.FieldType.string }]
return [{ field: 'title', type: tools.FieldType.string }];
};
CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
@@ -147,85 +174,102 @@ CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
};*/
CatalogSchema.statics.findAllIdApp = async function (idapp) {
try {
const arrrec = await this.aggregate([
{ $match: { idapp } },
{ $addFields: { num_lista_prodotti: { $size: { $ifNull: ['$lista_prodotti', []] } } } },
{ $project: { lista_prodotti: 0 } },
{ $sort: { title: 1 } },
]);
return arrrec;
} catch (err) {
console.error('Errore:', err);
throw err;
}
};
CatalogSchema.statics.getCatalogById = async function (id) {
const Catalog = this;
try {
let arrrec = await Catalog.find({ idapp })
.sort({ title: 1 }) // Ordina i risultati per titolo
/*.populate({
path: "idCollane", // Popola il campo idCollane
model: "Collana" // Specifica il modello della collezione Collana
})*/
let arrrec = await Catalog.find({ _id: id })
.populate({
path: "lista_prodotti", // Popola il campo lista_prodotti
path: 'lista_prodotti', // Popola il campo lista_prodotti
populate: {
path: "idProductInfo",
model: "ProductInfo",
path: 'idProductInfo',
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",
path: 'lista_prodotti',
populate: {
path: "idProducer",
model: "Producer"
}
path: 'idProducer',
model: 'Producer',
},
})
.populate({
path: "lista_prodotti",
path: 'lista_prodotti',
populate: {
path: "idProvider",
model: "Provider"
}
path: 'idProvider',
model: 'Provider',
},
})
.populate({
path: "lista_prodotti",
path: 'lista_prodotti',
populate: {
path: "idStorehouses",
model: "Storehouse"
}
path: 'idStorehouses',
model: 'Storehouse',
},
})
.populate({
path: "lista_prodotti",
path: 'lista_prodotti',
populate: {
path: "idScontisticas",
model: "Scontistica"
}
path: 'idScontisticas',
model: 'Scontistica',
},
})
.populate({
path: "lista_prodotti",
path: 'lista_prodotti',
populate: {
path: "idGasordine",
model: "Gasordine"
}
})
;
path: 'idGasordine',
model: 'Gasordine',
},
});
// 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);
catalog.lista_prodotti = catalog.lista_prodotti.filter(
(product) =>
product.idProductInfo &&
product.idProductInfo.code &&
product.idProductInfo.code !== '' &&
product.idProductInfo.imagefile &&
product.idProductInfo.imagefile !== 'noimg.jpg' &&
!product.delete
);
if (catalog.lista_prodotti.length !== originalLength) {
await catalog.save();
}
}
const transformedArrRec = arrrec.map(catalog => ({
const transformedArrRec = arrrec.map((catalog) => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
lista_prodotti: catalog.lista_prodotti.map((product) => ({
...product.toObject(),
productInfo: {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo
@@ -238,20 +282,44 @@ CatalogSchema.statics.findAllIdApp = async function (idapp) {
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
idProductInfo: product.idProductInfo._id, // CHECK
})),
}));
return transformedArrRec;
return transformedArrRec && transformedArrRec.length > 0 ? transformedArrRec[0] : null;
} catch (err) {
console.error('Errore: ', err);
return null;
}
};
CatalogSchema.statics.executeQueryPickup = async function (idapp, params) {
const strfind = params.search;
if (strfind === '') {
return [];
}
// Cerca title
const reg = new RegExp(strfind, 'i');
const arrrec = await this.find({
idapp,
title: reg,
})
.sort({ title: 1 })
.limit(10)
.select('title _id')
.lean();
return arrrec;
};
const Catalog = mongoose.model('Catalog', CatalogSchema);
Catalog.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});
module.exports = { Catalog };

View File

@@ -136,7 +136,7 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp, updateda
icon: 1,
color: 1,
quanti: { $size: '$myproducts' }, // Conta il numero di prodotti per ciascun CatProd
products: {
/*products: {
$map: {
input: "$myproducts",
as: "prod",
@@ -144,7 +144,7 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp, updateda
name: "$$prod.name"
}
}
}
}*/
}
},
{ $sort: { name: 1 } } // Ordina i risultati per nome

View File

@@ -1,4 +1,4 @@
const mongoose = require('mongoose').set('debug', false)
const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
const tools = require('../tools/general');
@@ -6,22 +6,22 @@ const { ObjectId } = require('mongodb');
const { MySchedaSchema, IDimensioni, IImg, IText, IAreaDiStampa } = require('../models/myscheda');
mongoose.Promise = global.Promise;
mongoose.level = "F";
mongoose.level = 'F';
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const IElementiPagina = new Schema({
isTemplate: Boolean,
linkIdTemplate: String,
name: String,
pagina: IDimensioni,
});
const myCard = new Schema(
{
const myCard = new Schema({
imagefile: String,
vers_img: Number,
alt: String,
@@ -32,31 +32,25 @@ const myCard = new Schema(
content: String,
colorsub: String,
link: String,
}
)
const animation = new Schema(
{
});
const animation = new Schema({
name: String,
clduration: String,
cldelay: String,
timingtype: String,
}
);
});
const elemText = new Schema(
{
const elemText = new Schema({
text: String,
color: String,
class: String,
size: String,
anim: animation,
}
);
});
const catalogo = new Schema(
{
const catalogo = new Schema({
//++AddCATALOGO_FIELDS
idCatalogSel: { type: String },
productTypes: [{ type: Number }],
excludeproductTypes: [{ type: Number }],
editore: [{ type: String }],
@@ -72,12 +66,16 @@ const catalogo = new Schema(
indebug: { type: Boolean },
maxnumlibri: { type: Number },
showListaArgomenti: { type: Boolean },
showOnlyCatalogoPDF: { type: Boolean },
showListaCollane: { type: Boolean },
first_page: IDimensioni,
last_page: IDimensioni,
areadistampa: IAreaDiStampa,
print_isTemplate: Boolean,
print_linkIdTemplate: String,
dimensioni_def: IElementiPagina,
// -------------------
@@ -90,10 +88,9 @@ const catalogo = new Schema(
type: [[mongoose.Schema.Types.Mixed]], // Definizione tipo
select: false // Imposta il campo come non selezionabile
},*/
}
},
],
}
);
});
const MyElemSchema = new Schema({
idapp: {
@@ -102,9 +99,9 @@ const MyElemSchema = new Schema({
path: {
type: String,
},
oldpath: {
/*oldpath: {
type: String,
},
},*/
idPage: { type: String },
type: {
type: Number,
@@ -237,25 +234,25 @@ const MyElemSchema = new Schema({
list: [
{
imagefile: {
type: String
type: String,
},
vers_img: {
type: Number,
},
order: {
type: Number
type: Number,
},
alt: {
type: String
type: String,
},
description: {
type: String
}
}
type: String,
},
},
],
date_created: {
type: Date,
default: Date.now
default: Date.now,
},
date_updated: {
type: Date,
@@ -271,8 +268,10 @@ MyElemSchema.pre('save', async function (next) {
});
MyElemSchema.statics.getFieldsForSearch = function () {
return [{ field: 'title', type: tools.FieldType.string },
{ field: 'content', type: tools.FieldType.string }]
return [
{ field: 'title', type: tools.FieldType.string },
{ field: 'content', type: tools.FieldType.string },
];
};
MyElemSchema.statics.executeQueryTable = function (idapp, params, user) {
@@ -292,7 +291,7 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
// Utilizza una mappa per accoppiare i path con i loro Id
const pathToIdMap = {};
pages.forEach(page => {
pages.forEach((page) => {
pathToIdMap[page.path] = page._id; // Mappa il path all'ID del documento MyPage
});
@@ -307,7 +306,7 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
idPage: id,
oldpath: path,
},
$unset: { path: "" } // Rimuove il campo path
$unset: { path: '' }, // Rimuove il campo path
} // Imposta IdPage all'ID del documento corrispondente
);
}
@@ -316,7 +315,7 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
if (false) {
// Utilizza una mappa per accoppiare i path con i loro Id
const pathToIdMap2 = {};
pages.forEach(page => {
pages.forEach((page) => {
pathToIdMap2[page.path] = page._id.toString(); // Mappa il path all'ID del documento MyPage
});
@@ -325,7 +324,7 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
await MyElem.updateMany(
{ oldpath: path }, // Condizione per aggiornare dove il path corrisponde
{
$unset: { idPage: "" } // Rimuove il campo path
$unset: { idPage: '' }, // Rimuove il campo path
} // Imposta IdPage all'ID del documento corrispondente
);
}
@@ -334,14 +333,14 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
await MyElem.updateMany(
{ oldpath: oldpath }, // Condizione per aggiornare dove il path corrisponde
{
$set: { idPage: id }
$set: { idPage: id },
} // Imposta IdPage all'ID del documento corrispondente
);
}
}
const pathToIdMap2 = {};
pages.forEach(page => {
pages.forEach((page) => {
pathToIdMap2[page.path] = page._id.toString(); // Mappa il path all'ID del documento MyPage
});
@@ -350,26 +349,23 @@ MyElemSchema.statics.SetIdPageInsteadThePah = async function (idapp) {
{ idapp },
{ oldpath: oldpath }, // Condizione per aggiornare dove il path corrisponde
{
$set: { idPage: id }
$set: { idPage: id },
} // Imposta IdPage all'ID del documento corrispondente
);
}
console.log('Aggiornamenti effettuati con successo.');
return 'Aggiornamenti effettuati con successo.';
} catch (error) {
console.error('Errore durante l\'aggiornamento:', error);
return 'Errore durante l\'aggiornamento:', error;
console.error("Errore durante l'aggiornamento:", error);
return "Errore durante l'aggiornamento:", error;
}
};
MyElemSchema.statics.deleteAllFromThisPage = async function (id) {
const MyElem = this;
return MyElem.deleteMany({ idPage: id });
};
MyElemSchema.statics.findAllIdApp = async function (idapp) {
const MyElem = this;
@@ -397,17 +393,16 @@ MyElemSchema.statics.findAllIdApp = async function (idapp) {
async function deleteOldMyElems(idapp) {
try {
const { MyPage } = require('../models/mypage');
// 1. Recupera tutti gli _id dalle pagine
const existingPages = await MyPage.find({ idapp }).select('_id').lean();
const existingPageIds = existingPages.map(page => page._id.toString());
const existingPageIds = existingPages.map((page) => page._id.toString());
// 2. Trova gli MyElem che hanno idPage non esistenti in MyPage
const elemsToDelete = await MyElem.find({
idapp,
idPage: { $nin: existingPageIds }
idPage: { $nin: existingPageIds },
});
if (elemsToDelete.length > 0) {
@@ -422,28 +417,38 @@ async function deleteOldMyElems(idapp) {
}
}
/**
* Trova tutte le schede template associate a pagine di idapp.
* Restituisce un array di ogge tti con le seguenti proprietà:
* - scheda: l'oggetto scheda, con proprietà come _id, name, isTemplate
* - idPageOrig: l'idPage originale associata alla scheda
*
* Se idapp === '18', stampa i duplicati e i titoli delle pagine
* e cancella i documenti di MyElem con idPage non esistenti in MyPage
*
* @param {string} idapp ID dell'applicazione
* @returns {Promise<IMyElemTemplate[]>} Array di oggetti scheda con idPageOrig
*/
MyElemSchema.statics.findallSchedeTemplate = async function (idapp) {
const MyElem = this;
try {
const { MyPage } = require('../models/mypage');
const ris = await MyElem.find({ idapp }).lean();
const schedeTemplate = ris.flatMap(elem =>
elem.catalogo && elem.catalogo.arrSchede ?
elem.catalogo.arrSchede
.filter(scheda => scheda.scheda?.isTemplate)
.map(scheda => ({
const schedeTemplate = ris.flatMap((elem) =>
elem.catalogo && elem.catalogo.arrSchede
? elem.catalogo.arrSchede
.filter((scheda) => scheda.scheda?.isTemplate)
.map((scheda) => ({
...scheda, // mantieni i dati originali della scheda
idPageOrig: elem.idPage // aggiungi l'idPage
idPageOrig: elem.idPage, // aggiungi l'idPage
}))
: []
);
if (idapp === '18') {
const duplicateIds = schedeTemplate.reduce((acc, scheda) => {
const id = scheda.scheda._id; // Ottieni l'ID della scheda
if (!acc[id]) {
@@ -459,7 +464,7 @@ MyElemSchema.statics.findallSchedeTemplate = async function (idapp) {
.map(([id, pages]) => ({ id, pages })); // Ottieni ID e pagine corrispondenti
// Recupera i dettagli delle pagine
const pageIds = duplicates.flatMap(dup => dup.pages); // Estrai tutti gli idPage
const pageIds = duplicates.flatMap((dup) => dup.pages); // Estrai tutti gli idPage
const pages = await MyPage.find({ idapp, _id: { $in: pageIds } }).lean();
// Crea una mappatura tra idPage e title
@@ -469,19 +474,18 @@ MyElemSchema.statics.findallSchedeTemplate = async function (idapp) {
}, {});
// Associa i titoli delle pagine agli ID duplicati
const resultWithTitles = duplicates.map(dup => ({
const resultWithTitles = duplicates.map((dup) => ({
id: dup.id,
pages: dup.pages.map(_id => ({
pages: dup.pages.map((_id) => ({
_id,
title: pageMap[_id] || 'Titolo non trovato' // Usa la mappatura per trovare il titolo
}))
title: pageMap[_id] || 'Titolo non trovato', // Usa la mappatura per trovare il titolo
})),
}));
if (resultWithTitles.length > 0) {
console.log('Duplicati e titoli delle pagine:', JSON.stringify(resultWithTitles, null, 2));
await deleteOldMyElems(idapp);
// await deleteOldMyElems(idapp);
}
}
return schedeTemplate;
@@ -490,35 +494,46 @@ MyElemSchema.statics.findallSchedeTemplate = async function (idapp) {
}
};
// Ricerca tra tutte le schede, contenute in catalogo, se esiste un nome di template uguale,
// se non lo trova allora è quello giusto per crearne uno nuovo
/**
* Ricerca tra tutte le schede, contenute in catalogo, se esiste un nome di template uguale,
* se non lo trova allora è quello giusto per crearne uno nuovo
*
* @param {string} idapp - ID dell'app
* @param {string} idPageOrig - ID della pagina originale
* @param {string} nomeTemplate - Nome del template
*
* @returns {string} Il nome del template libero
*/
MyElemSchema.statics.getNewFreeNameTemplate = async function (idapp, idPageOrig, nomeTemplate) {
const MyElem = this;
try {
// Trova tutti gli elementi che hanno un template con lo stesso nome
const ris = await MyElem.find(
{
idapp,
'catalogo.arrSchede.scheda.isTemplate': true,
'catalogo.arrSchede.scheda.idPage': { $ne: idPageOrig }
'catalogo.arrSchede.scheda.idPage': { $ne: idPageOrig },
},
{
'catalogo.arrSchede.scheda.name': 1,
'catalogo.arrSchede.scheda.isTemplate': 1,
'catalogo.arrSchede.scheda.isPagIntro': 1,
'catalogo.arrSchede.scheda.idPage': 1
});
'catalogo.arrSchede.scheda.idPage': 1,
}
);
// Recupera i nomi dei template già esistenti
const existingNames = new Set(
ris.flatMap(elem =>
elem.catalogo?.arrSchede?.filter(scheda =>
scheda.scheda?.isTemplate &&
scheda.scheda?.idPage !== idPageOrig
)
.map(scheda => scheda.scheda?.name) || []
ris.flatMap(
(elem) =>
elem.catalogo?.arrSchede
?.filter((scheda) => scheda.scheda?.isTemplate && scheda.scheda?.idPage !== idPageOrig)
.map((scheda) => scheda.scheda?.name) || []
)
);
// Crea un nuovo nome di template univoco
let ind = 2;
let newNameTemplate;
@@ -538,7 +553,8 @@ const MyElem = mongoose.model('MyElem', MyElemSchema);
MyElem.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});
module.exports = { MyElem };

View File

@@ -11,7 +11,7 @@ mongoose.level = 'F';
const { ObjectId } = require('mongodb');
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
@@ -34,9 +34,11 @@ const MyGroupSchema = new Schema({
descr: {
type: String,
},
idCatGrp: [{
idCatGrp: [
{
type: Number,
}],
},
],
userId: {
type: String,
},
@@ -51,11 +53,13 @@ const MyGroupSchema = new Schema({
description: {
type: String,
},
}],
},
],
idCity: [
{
type: Number,
}],
},
],
website: {
type: String,
},
@@ -104,13 +108,15 @@ const MyGroupSchema = new Schema({
_id: false,
username: { type: String },
date: { type: Date },
}], // username
},
], // username
refused_users: [
{
_id: false,
username: { type: String },
date: { type: Date },
}], // username
},
], // username
deleted: {
type: Boolean,
default: false,
@@ -120,18 +126,22 @@ const MyGroupSchema = new Schema({
_id: false,
circuitname: { type: String },
date: { type: Date },
}],
},
],
lastdate_reqRisGroup: {
type: Date,
},
//**ADDFIELD_MYGROUPS
...tools.getFieldsForAnnunci(),
});
MyGroupSchema.statics.getFieldsForSearch = function () {
return [{ field: 'descr', type: tools.FieldType.string }];
return [
{ field: 'descr', type: tools.FieldType.string },
{ field: 'groupname', type: tools.FieldType.string },
{ field: 'title', type: tools.FieldType.string },
];
};
MyGroupSchema.statics.executeQueryTable = function (idapp, params, user) {
@@ -139,21 +149,20 @@ MyGroupSchema.statics.executeQueryTable = function (idapp, params, user) {
const { User } = require('./user');
if (params.options) {
/*if (params.options) {
if (tools.isBitActive(params.options, shared_consts.OPTIONS_SEARCH_USER_ONLY_FULL_WORDS)) {
params.fieldsearch = User.getFieldsForSearchUserFriend();
} else if (tools.isBitActive(params.options, shared_consts.OPTIONS_SEARCH_USER_ALL_WORDS)) {
params.fieldsearch = User.getFieldsForSearchUserFriend_AllWords();
}
}
}*/
return tools.executeQueryTable(this, idapp, params, user);
};
MyGroupSchema.pre('save', async function (next) {
if (this.isNew) {
if (!this.date_created)
this.date_created = new Date();
if (!this.date_created) this.date_created = new Date();
}
next();
@@ -166,75 +175,74 @@ MyGroupSchema.statics.findAllIdApp = async function (idapp) {
};
MyGroupSchema.statics.findAllGroups = async function (idapp) {
const whatToShow = this.getWhatToShow(idapp, '');
return await MyGroup.find({
return await MyGroup.find(
{
idapp,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow).lean();
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow
).lean();
};
// Rimuovo la Richiesta del Gruppo
MyGroupSchema.statics.removeReqGroup = async function (idapp, username, groupnameDest) {
return await MyGroup.updateOne({ idapp, groupname: groupnameDest },
{ $pull: { req_users: { username: { $in: [username] } } } });
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{ $pull: { req_users: { username: { $in: [username] } } } }
);
};
// Aggiungi agli utenti Rifiutati del Gruppo
MyGroupSchema.statics.refuseReqGroup = async function (idapp, username, groupnameDest) {
return await MyGroup.updateOne({ idapp, groupname: groupnameDest },
{
$push:
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{
$push: {
refused_users: {
username,
date: new Date(),
},
},
});
}
);
};
// Aggiungi agli Admin del Gruppo
MyGroupSchema.statics.addToAdminOfMyGroup = async function (idapp, username, groupnameDest) {
return await MyGroup.updateOne({ idapp, groupname: groupnameDest },
{
$push:
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{
$push: {
admins: {
username,
date: new Date(),
},
},
});
}
);
};
// Rimuovi dagli Admin del Gruppo
MyGroupSchema.statics.removeAdminOfMyGroup = async function (idapp, username, groupnameDest) {
return await MyGroup.updateOne({ idapp, groupname: groupnameDest },
{ $pull: { admins: { username: { $in: [username] } } } });
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{ $pull: { admins: { username: { $in: [username] } } } }
);
};
MyGroupSchema.statics.getListAdminsByGroupName = async function (idapp, groupname) {
let arr = await MyGroup.findOne({
let arr = await MyGroup.findOne(
{
idapp,
groupname,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, { admins: 1 }).lean();
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
{ admins: 1 }
).lean();
return arr && arr.admins ? arr.admins : [];
};
MyGroupSchema.statics.getWhatToShow = function (idapp, username) {
@@ -267,7 +275,6 @@ MyGroupSchema.statics.getWhatToShow = function (idapp, username) {
whatToShow = { ...whatToShow, ...shared_consts.ANNUNCI_FIELDS };
return whatToShow;
};
MyGroupSchema.statics.getWhatToShow_Unknown = function (idapp, username) {
@@ -289,32 +296,30 @@ MyGroupSchema.statics.getWhatToShow_Unknown = function (idapp, username) {
whatToShow = { ...whatToShow, ...shared_consts.ANNUNCI_FIELDS };
return whatToShow;
};
MyGroupSchema.statics.getArrUsernameFromFieldByGroupname = async function (
idapp, groupname, field) {
MyGroupSchema.statics.getArrUsernameFromFieldByGroupname = async function (idapp, groupname, field) {
const { User } = require('../models/user');
const myobj = {};
myobj[field] = 1;
const ris = await User.findOne({
const ris = await User.findOne(
{
idapp,
groupname,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
}, myobj);
},
myobj
);
if (ris) {
return ris[field].map(m => m.username);
return ris[field].map((m) => m.username);
}
return [];
};
MyGroupSchema.statics.getInfoGroupByGroupname = async function (idapp, groupname) {
const whatToShow = this.getWhatToShow(idapp, groupname);
const myfind = {
@@ -333,14 +338,11 @@ MyGroupSchema.statics.getInfoGroupByGroupname = async function (idapp, groupname
},
},
{
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
$replaceRoot: {
newRoot: {
$mergeObjects: [
{
'$arrayElemAt': [
'$mycircuits',
0,
],
$arrayElemAt: ['$mycircuits', 0],
},
'$$ROOT',
],
@@ -359,21 +361,17 @@ MyGroupSchema.statics.getInfoGroupByGroupname = async function (idapp, groupname
{
$project: shared_consts.getProjectByTable(shared_consts.TABLES_MYGROUPS, {}),
},
];
try {
const ris = await MyGroup.aggregate(query);
if (ris && ris.length > 0)
return ris[0];
if (ris && ris.length > 0) return ris[0];
} catch (e) {
return null;
}
return null;
};
MyGroupSchema.statics.deleteGroup = async function (idapp, usernameOrig, groupname) {
@@ -382,7 +380,6 @@ MyGroupSchema.statics.deleteGroup = async function (idapp, usernameOrig, groupna
};
MyGroupSchema.statics.getGroupsByUsername = async function (idapp, username, req) {
try {
const { User } = require('../models/user');
@@ -391,20 +388,22 @@ MyGroupSchema.statics.getGroupsByUsername = async function (idapp, username, req
const arrUsernameGroups = await User.getUsernameGroupsByUsername(idapp, username);
// const arrUsernameReqGroups = await MyGroup.getUsernameReqGroupsByGroupname(idapp, username);
let listUsersGroup = await User.find({
let listUsersGroup = await User.find(
{
idapp,
username: { $in: arrUsernameGroups },
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow);
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow
);
let listgroups = await MyGroup.find({
let listgroups = await MyGroup.find(
{
idapp,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow_Unknown
);
/*let listRequestUsersGroup = await User.find({
idapp,
@@ -416,25 +415,27 @@ MyGroupSchema.statics.getGroupsByUsername = async function (idapp, username, req
*/
let listSentRequestGroups = await MyGroup.find({
let listSentRequestGroups = await MyGroup.find(
{
idapp,
'req_users': {
req_users: {
$elemMatch: { username: { $eq: username } },
},
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow_Unknown
);
let listRefusedGroups = await MyGroup.find({
let listRefusedGroups = await MyGroup.find(
{
idapp,
'refused_users': {
refused_users: {
$elemMatch: { username: { $eq: username } },
},
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow_Unknown
);
return {
listUsersGroup,
@@ -443,7 +444,6 @@ MyGroupSchema.statics.getGroupsByUsername = async function (idapp, username, req
listRefusedGroups,
mygroups: await User.getMyGroupsById(req.user._id),
};
} catch (e) {
console.log('Error', e);
}
@@ -454,12 +454,10 @@ MyGroupSchema.statics.getGroupsByUsername = async function (idapp, username, req
listTrusted: [],
listSentRequestGroups: [],
listRefusedGroups: [],
};
};
MyGroupSchema.statics.extractCitiesName = async function (idapp, id) {
try {
let aggr1 = [
{
@@ -474,14 +472,11 @@ MyGroupSchema.statics.extractCitiesName = async function (idapp, id) {
},
},
{
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
$replaceRoot: {
newRoot: {
$mergeObjects: [
{
'$arrayElemAt': [
'$mycities',
0,
],
$arrayElemAt: ['$mycities', 0],
},
'$$ROOT',
],
@@ -490,8 +485,8 @@ MyGroupSchema.statics.extractCitiesName = async function (idapp, id) {
},
{
$project: {
"mycities.comune": 1,
"mycities.prov": 1
'mycities.comune': 1,
'mycities.prov': 1,
},
},
];
@@ -502,16 +497,14 @@ MyGroupSchema.statics.extractCitiesName = async function (idapp, id) {
} catch (e) {
console.error('e', e);
}
};
MyGroupSchema.statics.ifCircuitAlreadyInGroup = async function (idapp, groupname, circuitname) {
// Controllo se è stato già inserito il circuito sul gruppo
return await this.findOne({
idapp,
groupname,
'mycircuits': {
mycircuits: {
$elemMatch: { circuitname: { $eq: circuitname } },
},
}).lean();
@@ -519,70 +512,70 @@ MyGroupSchema.statics.ifCircuitAlreadyInGroup = async function (idapp, groupname
// aggiungo il Circuito all'interno del Gruppo
MyGroupSchema.statics.addCircuitFromGroup = async function (idapp, groupname, circuitname) {
return await this.updateOne({ idapp, groupname },
return await this.updateOne(
{ idapp, groupname },
{
$push: {
'mycircuits': {
mycircuits: {
circuitname,
date: new Date(),
},
},
}
}
});
);
};
// Rimuovo il Circuito all'interno del Gruppo
MyGroupSchema.statics.removeCircuitFromGroup = async function (idapp, groupname, circuitname) {
const { Circuit } = require('../models/circuit');
const { Account } = require('../models/account');
const ris = await this.updateOne({ idapp, groupname },
{ $pull: { 'mycircuits': { circuitname: { $in: [circuitname] } } } });
const ris = await this.updateOne(
{ idapp, groupname },
{ $pull: { mycircuits: { circuitname: { $in: [circuitname] } } } }
);
const circuitId = await Circuit.getCircuitIdByName(idapp, circuitname);
let remove = false;
// Se il mio account non è stato utilizzato, allora lo cancello anche questo
const myaccount = await Account.getAccountByUsernameAndCircuitId(idapp, username, circuitId, false, false, groupname, '');
const myaccount = await Account.getAccountByUsernameAndCircuitId(idapp, '', circuitId, false, false, groupname, '');
if (myaccount && myaccount.totTransato === 0) {
remove = true;
} else {
remove = true;
}
if (remove) {
if (remove && myaccount) {
await Account.removeAccount(myaccount._id);
}
};
MyGroupSchema.statics.getQueryReceiveRISGroups = function (idapp, hours) {
const query = [
{
$match: {
idapp,
'lastdate_reqRisGroup': { $gte: tools.IncDateNow(-(1000 * 60 * 60 * hours)) },
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
lastdate_reqRisGroup: { $gte: tools.IncDateNow(-(1000 * 60 * 60 * hours)) },
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
},
{
$group:
{
_id: "$groupname",
$group: {
_id: '$groupname',
count: {
$sum: 1,
},
}
},
{ $sort: { 'lastdate_reqRisGroup': -1 } },
},
{ $sort: { lastdate_reqRisGroup: -1 } },
{ $limit: 30 },
{
$lookup: {
from: "mygroups",
from: 'mygroups',
let: {
groupname: "$_id",
groupname: '$_id',
idapp,
},
pipeline: [
@@ -591,30 +584,24 @@ MyGroupSchema.statics.getQueryReceiveRISGroups = function (idapp, hours) {
$expr: {
$and: [
{
$eq: [
"$$groupname",
"$groupname",
],
$eq: ['$$groupname', '$groupname'],
},
{
$eq: [
"$$idapp",
"$idapp",
],
$eq: ['$$idapp', '$idapp'],
},
],
},
},
},
],
as: "mygroup",
as: 'mygroup',
},
},
{ $unwind: "$mygroup" },
{ $unwind: '$mygroup' },
{
$replaceRoot: {
newRoot: {
$mergeObjects: ["$mygroup", "$$ROOT"],
$mergeObjects: ['$mygroup', '$$ROOT'],
},
},
},
@@ -645,27 +632,23 @@ MyGroupSchema.statics.getQueryReceiveRISGroups = function (idapp, hours) {
return query;
};
MyGroupSchema.statics.getReceiveRISGroups = async function (idapp) {
return await this.aggregate(this.getQueryReceiveRISGroups(idapp, 8)).then(ris => {
return await this.aggregate(this.getQueryReceiveRISGroups(idapp, 8)).then((ris) => {
return ris;
});
};
MyGroupSchema.statics.renameCircuitName = async function (idapp, oldcircuitname, newcircuitname) {
return await this.updateMany({ idapp, 'mycircuits.circuitname': oldcircuitname }, { $set: { 'profile.mycircuits.$.circuitname': newcircuitname } });
return await this.updateMany(
{ idapp, 'mycircuits.circuitname': oldcircuitname },
{ $set: { 'profile.mycircuits.$.circuitname': newcircuitname } }
);
};
MyGroupSchema.statics.setReceiveRisGroup = async function (idapp, groupname) {
const record = await this.findOneAndUpdate(
{ idapp, groupname },
{ $set: { 'lastdate_reqRisGroup': new Date() } },
{ $set: { lastdate_reqRisGroup: new Date() } },
{ new: false }
).lean();
@@ -676,7 +659,8 @@ const MyGroup = mongoose.model('MyGroup', MyGroupSchema);
MyGroup.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});
module.exports = { MyGroup };

View File

@@ -28,6 +28,9 @@ const MyPageSchema = new Schema({
subtitle: {
type: String,
},
isTemplate: {
type: Boolean,
},
icon: {
type: String,
},
@@ -56,6 +59,12 @@ const MyPageSchema = new Schema({
only_residenti: {
type: Boolean,
},
only_admin: {
type: Boolean,
},
only_collab: {
type: Boolean,
},
color: {
type: String,
},
@@ -137,6 +146,9 @@ const MyPageSchema = new Schema({
sottoMenu: [{
type: String
}],
hideHeader: {
type: Boolean,
},
date_created: {
type: Date,
default: Date.now
@@ -199,7 +211,10 @@ MyPageSchema.statics.findOnlyStruttRec = async function (idapp) {
path: 1,
active: 1,
onlyif_logged: 1,
isTemplate: 1,
only_residenti: 1,
only_admin: 1,
only_collab: 1,
inmenu: 1,
submenu: 1,
iconsize: 1,
@@ -227,6 +242,8 @@ MyPageSchema.statics.findInternalPages = async function (idapp) {
path: 1,
onlyif_logged: 1,
only_residenti: 1,
only_admin: 1,
only_collab: 1,
}).lean();
return result;

View File

@@ -65,10 +65,13 @@ const IAreaDiStampa = new Schema({
margini: IBorders,
unit: String,
format: [{ type: Number }],
format_printable: [{ type: Number }],
orientation: String,
compress: Boolean,
scale: Number,
scale_printable: Number,
scalex: Number,
scaley: Number,
scale_printablex: Number,
scale_printabley: Number,
scalecanvas: Number,
});
@@ -116,6 +119,8 @@ const scheletroScheda = {
isTemplate: { type: Boolean },
isPagIntro: { type: Boolean },
linkIdTemplate: { type: String },
scalexscheda: Number,
scaleyscheda: Number,
name: { type: String },
numschede_perRiga: { type: Number },
numschede_perCol: { type: Number },

View File

@@ -0,0 +1,99 @@
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 MyScrapingBookSchema = new Schema({
isbn: {
type: String,
index: true,
},
isbn10: {
type: String,
},
fonte: {
type: String,
},
titolo: {
type: String,
},
titoloOriginale: {
type: String,
},
sottotitolo: {
type: String,
},
autore: {
type: String,
},
pagine: {
type: String,
},
misure: {
type: String,
},
edizione: {
type: String,
},
editore: {
type: String,
},
date_pub: {
type: Date,
},
url: {
type: String,
},
stelline: {
type: Number,
},
prezzo: {
type: String,
},
date_extraction: {
type: Date,
},
descrizione_lunga: {
type: String,
},
});
MyScrapingBookSchema.statics.getFieldsForSearch = function () {
return [{ field: 'titolo', type: tools.FieldType.string }];
};
MyScrapingBookSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
MyScrapingBookSchema.statics.findAllIdApp = async function (idapp) {
const MyScrapingBook = this;
const myfind = { idapp };
try {
return await MyScrapingBook.find(myfind).sort({ titolo: 1 }).lean();
} catch (err) {
console.error('Errore in MyScrapingBook:', err, model);
return null;
}
};
const MyScrapingBook = mongoose.model('MyScrapingBook', MyScrapingBookSchema);
MyScrapingBook.createIndexes()
.then(() => {})
.catch((err) => {
throw err;
});
module.exports = { MyScrapingBook };

View File

@@ -1,19 +1,21 @@
const mongoose = require('mongoose').set('debug', false)
const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
const shared_consts = require('../tools/shared_nodejs');
const { ObjectId } = require('mongodb');
mongoose.Promise = global.Promise;
mongoose.level = "F";
const Scontistica = require('../models/scontistica');
const OrderClass = require('../modules/OrderClass');
const fs = require('fs');
mongoose.Promise = global.Promise;
mongoose.level = 'F';
const fs = require('fs'); // 👈 Usa il modulo promises
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const orderSchema = new Schema({
@@ -22,7 +24,8 @@ const orderSchema = new Schema({
},
userId: { type: Schema.Types.ObjectId, ref: 'User' },
status: {
type: Number, index: true
type: Number,
index: true,
},
idProduct: { type: Schema.Types.ObjectId, ref: 'Product', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
@@ -35,13 +38,13 @@ const orderSchema = new Schema({
default: 0,
},
after_price: {
type: String
type: String,
},
color: {
type: String
type: String,
},
size: {
type: String
type: String,
},
quantity: {
type: Number,
@@ -62,83 +65,89 @@ const orderSchema = new Schema({
type: Number,
default: 0,
},
confermato: { // e quindi è stato tolto dal magazzino (aggiornando il campo stockQty)
confermato: {
// e quindi è stato tolto dal magazzino (aggiornando il campo stockQty)
type: Boolean,
default: false,
},
date_confermato: {
type: Date
type: Date,
},
pagato: {
type: Boolean,
default: false,
},
date_pagato: {
type: Date
type: Date,
},
consegnato: {
type: Boolean,
default: false,
},
date_consegnato: {
type: Date
type: Date,
},
spedito: {
type: Boolean,
default: false,
},
date_spedito: {
type: Date
type: Date,
},
ricevuto: {
type: Boolean,
default: false,
},
date_ricevuto: {
type: Date
type: Date,
},
weight: {
type: Number
type: Number,
},
unit: {
type: Number
type: Number,
},
stars: {
type: Number
type: Number,
},
date_created: {
type: Date
type: Date,
},
date_checkout: {
type: Date
type: Date,
},
date_payment: {
type: Date
type: Date,
},
date_shipping: {
type: Date
type: Date,
},
date_delivered: {
type: Date
type: Date,
},
note: {
type: String
type: String,
},
codice_sconto: {
type: String,
},
modify_at: {
type: Date,
index: true
index: true,
},
});
var Order = module.exports = mongoose.model('Order', orderSchema);
var Order = (module.exports = mongoose.model('Order', orderSchema));
module.exports.createIndexes()
module.exports
.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});
module.exports.getFieldsForSearch = function () {
return []
return [];
};
module.exports.executeQueryTable = function (idapp, params) {
@@ -149,7 +158,6 @@ module.exports.executeQueryTable = function (idapp, params) {
};
module.exports.findAllIdApp = async function (idapp) {
const query = [
{ $match: { idapp } },
{
@@ -157,16 +165,16 @@ module.exports.findAllIdApp = async function (idapp) {
from: 'products',
localField: 'idProduct',
foreignField: '_id',
as: 'product'
}
as: 'product',
},
},
{
$lookup: {
from: 'productinfos',
localField: 'product.idProduct',
foreignField: '_id',
as: 'product.productInfo'
}
as: 'product.productInfo',
},
},
{
$unwind: {
@@ -179,24 +187,24 @@ module.exports.findAllIdApp = async function (idapp) {
from: 'producers',
localField: 'product.idProducer',
foreignField: '_id',
as: 'producer'
}
as: 'producer',
},
},
{
$lookup: {
from: 'providers',
localField: 'product.idProvider',
foreignField: '_id',
as: 'provider'
}
as: 'provider',
},
},
{
$lookup: {
from: 'gasordines',
localField: 'idGasordine',
foreignField: '_id',
as: 'gasordine'
}
as: 'gasordine',
},
},
{
$unwind: {
@@ -206,19 +214,16 @@ module.exports.findAllIdApp = async function (idapp) {
},
{
$match: {
$or: [
{ 'gasordine': { $exists: false } },
{ 'gasordine.active': true }
]
}
$or: [{ gasordine: { $exists: false } }, { 'gasordine.active': true }],
},
},
{
$lookup: {
from: 'scontisticas',
localField: 'product.idScontisticas',
foreignField: '_id',
as: 'scontistica'
}
as: 'scontistica',
},
},
{
$unwind: {
@@ -238,144 +243,103 @@ module.exports.findAllIdApp = async function (idapp) {
preserveNullAndEmptyArrays: true,
},
},
];
return await Order.aggregate(query)
return await Order.aggregate(query);
};
module.exports.getAllOrders = function (query, sort, callback) {
Order.find(query, null, sort, callback)
}
Order.find(query, null, sort, callback);
};
module.exports.getOrderByUserId = function (userId, sort, callback) {
Order.find({ userId }, null, sort, callback)
}
Order.find({ userId }, null, sort, callback);
};
module.exports.getOrderByID = function (id, callback) {
Order.findById(id, callback);
}
module.exports.createOrder = async function (order) {
};
module.exports.createOrder = async function (order, codice_sconto) {
try {
if (order.idGasordine === '') {
order.idGasordine = undefined;
}
Order.updateTotals(order);
return await Order.create(order)
.then((ris) => {
if (!!ris)
return ris._id;
await Order.updateTotals(order, codice_sconto);
return await Order.create(order).then((ris) => {
if (!!ris) return ris._id;
return null;
});
} catch (e) {
console.error('err', e);
}
}
};
module.exports.updateStatusOrders = async function (arrOrders, status) {
for (const order of arrOrders) {
let ret = await Order.updateOne({ _id: order.order._id }, { $set: { status } });
}
}
};
module.exports.updateStatusOrdersElements = async function (arrOrders, myelements) {
for (const order of arrOrders) {
const ret = await Order.findOneAndUpdate({ _id: order.order._id }, { $set: myelements });
}
}
};
module.exports.updateOrderByParams = async function (idOrder, paramstoupdate) {
const ris = await Order.findOneAndUpdate({ _id: idOrder }, { $set: paramstoupdate });
let myorder = await Order.findOne({ _id: idOrder }).lean();
if (paramstoupdate && !paramstoupdate.hasOwnProperty('TotalPriceProduct')) {
this.updateTotals(myorder);
await this.updateTotals(myorder);
await Order.findOneAndUpdate({ _id: idOrder }, { $set: myorder });
}
return myorder;
}
module.exports.updateTotals = function (order) {
};
module.exports.updateTotals = async function (order, codice_sconto) {
try {
if (!order) {
return;
const CartClass = require('../modules/Cart');
if (!order) return;
OrderClass.initOrderTotals(order);
let total = 0;
let scontoapplicato = false;
let recscontisticheTrovate = [];
if (codice_sconto) {
recscontisticheTrovate = await CartClass.getRecSconto(order.idapp, codice_sconto, true);
}
let mypricecalc = 0;
order.TotalPriceProduct = 0;
order.TotalPriceProductCalc = 0;
order.modify_at = new Date();
// Calcolo Sconto
let sconti_da_applicare = [];
if (order.scontisticas) {
let qtadascontare = order.quantity + order.quantitypreordered
let qtanonscontata = 0
while (qtadascontare > 0) {
let scontoapplicato = null
for (const sconto of order.scontisticas.filter((rec) => !rec.cumulativo)) {
if (qtadascontare >= sconto.qta) {
scontoapplicato = sconto
scontoapplicato.qtadascontare = sconto.qta
}
}
if (scontoapplicato && scontoapplicato.qtadascontare > 0) {
sconti_da_applicare.push(scontoapplicato)
qtadascontare -= scontoapplicato.qtadascontare
// Se ha inserito una scontistica che esiste...
if (recscontisticheTrovate && recscontisticheTrovate.length > 0) {
const { sconti_da_applicare, qtanonscontata } = OrderClass.applyNonCumulativeDiscounts(order, recscontisticheTrovate);
total = OrderClass.calculateDiscountedPrice(order, sconti_da_applicare, qtanonscontata);
} else if (order.scontisticas && order.scontisticas.length > 0) {
const { sconti_da_applicare, qtanonscontata } = OrderClass.applyNonCumulativeDiscounts(order, order.scontisticas);
total = OrderClass.calculateDiscountedPrice(order, sconti_da_applicare, qtanonscontata);
} else {
qtanonscontata = qtadascontare
qtadascontare = 0
}
total = OrderClass.calculateFullPrice(order);
}
/*for (const sconto of order.scontisticas.filter((rec) => rec.cumulativo)) {
if ((sconto.qta % order.quantity) === 0) {
sconti_da_applicare.push(sconto)
}
}*/
if (sconti_da_applicare.length > 0) {
for (const sconto of sconti_da_applicare) {
if (sconto.perc_sconto > 0) {
mypricecalc += (sconto.qtadascontare * order.price) * (1 - (sconto.perc_sconto / 100))
} else {
mypricecalc += sconto.price
}
}
}
if (qtanonscontata > 0) {
mypricecalc += order.price * qtanonscontata;
}
} else {
mypricecalc = (order.price * order.quantity) + (order.price * order.quantitypreordered);
}
order.TotalPriceProductCalc += mypricecalc;
order.TotalPriceProduct += mypricecalc;
order.TotalPriceProductCalc += total;
order.TotalPriceProduct += total;
order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2));
order.codice_sconto = codice_sconto;
return order;
} catch (e) {
console.error('Err:', e);
}
}
};
module.exports.getTotalOrderById = async function (id) {
const query = [
@@ -385,8 +349,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'products',
localField: 'idProduct',
foreignField: '_id',
as: 'product'
}
as: 'product',
},
},
{
$unwind: {
@@ -399,8 +363,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'productinfos',
localField: 'product.idProductInfo',
foreignField: '_id',
as: 'product.productInfo'
}
as: 'product.productInfo',
},
},
{
$unwind: {
@@ -413,8 +377,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'producers',
localField: 'product.idProducer',
foreignField: '_id',
as: 'producer'
}
as: 'producer',
},
},
{
$unwind: {
@@ -427,8 +391,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'storehouses',
localField: 'idStorehouse',
foreignField: '_id',
as: 'storehouse'
}
as: 'storehouse',
},
},
{
$unwind: {
@@ -441,8 +405,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'providers',
localField: 'product.idProvider',
foreignField: '_id',
as: 'provider'
}
as: 'provider',
},
},
{
$unwind: {
@@ -455,8 +419,8 @@ module.exports.getTotalOrderById = async function (id) {
from: 'gasordines',
localField: 'idGasordine',
foreignField: '_id',
as: 'gasordine'
}
as: 'gasordine',
},
},
{
$unwind: {
@@ -466,19 +430,16 @@ module.exports.getTotalOrderById = async function (id) {
},
{
$match: {
$or: [
{ 'gasordine': { $exists: false } },
{ 'gasordine.active': true }
]
}
$or: [{ gasordine: { $exists: false } }, { 'gasordine.active': true }],
},
},
{
$lookup: {
from: 'scontisticas',
localField: 'product.idScontisticas',
foreignField: '_id',
as: 'scontisticas'
}
as: 'scontisticas',
},
},
{
$lookup: {
@@ -493,32 +454,34 @@ module.exports.getTotalOrderById = async function (id) {
{
$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
]
}]
}
]
}
]
}
{ $subtract: [new Date(), 60 * 60 * 1000] }, // 1 hour in milliseconds 60 * 60
],
},
],
},
],
},
],
},
},
},
{
$group: {
_id: null,
totalQty: { $sum: '$quantity' },
}
}
},
},
],
as: 'productOrders'
}
as: 'productOrders',
},
},
{
$lookup: {
@@ -533,32 +496,34 @@ module.exports.getTotalOrderById = async function (id) {
{
$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
]
}]
}
]
}
]
}
}
{ $subtract: [new Date(), 60 * 60 * 1000] }, // 1 hour in milliseconds 60 * 60
],
},
],
},
],
},
],
},
},
},
{
$group: {
_id: null,
totalQtyPreordered: { $sum: '$quantitypreordered' }
}
}
totalQtyPreordered: { $sum: '$quantitypreordered' },
},
},
],
as: 'productPreOrders'
}
as: 'productPreOrders',
},
},
{
$addFields: {
@@ -568,11 +533,11 @@ module.exports.getTotalOrderById = async function (id) {
$cond: {
if: { $isArray: '$productOrders' },
then: { $arrayElemAt: ['$productOrders.totalQty', 0] },
else: 0
}
else: 0,
},
0
]
},
0,
],
},
'product.QuantitaPrenotateInAttesa': {
$ifNull: [
@@ -580,36 +545,35 @@ module.exports.getTotalOrderById = async function (id) {
$cond: {
if: { $isArray: '$productPreOrders' },
then: { $arrayElemAt: ['$productPreOrders.totalQtyPreordered', 0] },
else: 0
}
else: 0,
},
0
]
},
0,
],
},
},
},
{
$addFields: {
'product.quantityAvailable': {
$subtract: ["$product.stockQty", "$product.QuantitaOrdinateInAttesa"],
$subtract: ['$product.stockQty', '$product.QuantitaOrdinateInAttesa'],
},
'product.bookableAvailableQty': {
$subtract: ["$product.maxbookableGASQty", "$product.QuantitaPrenotateInAttesa"],
}
}
$subtract: ['$product.maxbookableGASQty', '$product.QuantitaPrenotateInAttesa'],
},
},
},
{
$unset: 'productOrders'
$unset: 'productOrders',
},
{
$unset: 'productPreOrders'
$unset: 'productPreOrders',
},
];
const ris = await Order.aggregate(query);
return ris;
}
};
module.exports.RemoveDeletedOrdersInOrderscart = async function () {
try {
@@ -620,11 +584,11 @@ module.exports.RemoveDeletedOrdersInOrderscart = async function () {
for (const rec of arrorders) {
let recordercart = await OrdersCart.getOrdersCartById(rec._id);
let arrord = []
let arrord = [];
let cambiare = false;
for (const recOrd of recordercart.items) {
if (recOrd.order) {
arrord.push(recOrd)
arrord.push(recOrd);
} else {
cambiare = true;
}
@@ -647,18 +611,14 @@ module.exports.RemoveDeletedOrdersInOrderscart = async function () {
await Order.findOneAndDelete({ _id: ord._id });
}
})
.catch(err => console.error(err));
.catch((err) => console.error(err));
}
} catch (e) {
console.error('Err', e);
}
};
module.exports.GeneraCSVOrdineProdotti = async function () {
const myidGasordine = '65c2a8cc379ee4f57e865ee7';
const myquery = [
@@ -668,8 +628,8 @@ module.exports.GeneraCSVOrdineProdotti = async function () {
from: 'products',
localField: 'idProduct',
foreignField: '_id',
as: 'product'
}
as: 'product',
},
},
{
$unwind: {
@@ -682,8 +642,8 @@ module.exports.GeneraCSVOrdineProdotti = async function () {
from: 'productinfos',
localField: 'product.idProductInfo',
foreignField: '_id',
as: 'productInfo'
}
as: 'productInfo',
},
},
{
$unwind: {
@@ -695,8 +655,8 @@ module.exports.GeneraCSVOrdineProdotti = async function () {
from: 'gasordines',
localField: 'idGasordine',
foreignField: '_id',
as: 'gasordine'
}
as: 'gasordine',
},
},
{
$unwind: {
@@ -708,66 +668,56 @@ module.exports.GeneraCSVOrdineProdotti = async function () {
$match: {
$or: [
{ 'gasordine.active': true }, // Include documents where gasordines.active is true
{ 'gasordine': { $exists: false } } // Include documents where gasordines array doesn't exist
]
}
{ gasordine: { $exists: false } }, // Include documents where gasordines array doesn't exist
],
},
},
{
$match: {
$or: [
{ quantity: { $gt: 0 }, },
{ quantitypreordered: { $gt: 0 }, }
]
}
$or: [{ quantity: { $gt: 0 } }, { quantitypreordered: { $gt: 0 } }],
},
},
{
$group: {
_id: "$product._id",
name: { $first: "$productInfo.name" },
weight: { $first: "$productInfo.weight" },
price_acquistato: { $first: "$product.price_acquistato" },
totalQuantity: { $sum: { $add: ["$quantity", "$quantitypreordered"] } },
totalPrice_acquistato: { $sum: { $multiply: ["$product.price_acquistato", { $add: ["$quantity", "$quantitypreordered"] }] } },
count: { $sum: 1 }
}
_id: '$product._id',
name: { $first: '$productInfo.name' },
weight: { $first: '$productInfo.weight' },
price_acquistato: { $first: '$product.price_acquistato' },
totalQuantity: { $sum: { $add: ['$quantity', '$quantitypreordered'] } },
totalPrice_acquistato: {
$sum: { $multiply: ['$product.price_acquistato', { $add: ['$quantity', '$quantitypreordered'] }] },
},
count: { $sum: 1 },
},
},
{
$sort: {
name: 1 // Sort in ascending order based on the "date_created" field
name: 1, // Sort in ascending order based on the "date_created" field
},
},
}
];
let myorderscart = await Order.aggregate(myquery);
console.log(myorderscart)
console.log(myorderscart);
return generateCSV(myorderscart, 'outout.csv');
}
};
function generateCSV(data, outputPath) {
const headers = ['Num', 'Nome', 'Peso', 'Prezzo', 'Quantita', 'Totale', 'Ordini'];
const rows = data.map(item => {
const rows = data.map((item) => {
const formattedPrice = item.price_acquistato.toString().replace(/\./g, ','); // Converti "." in ","
const total = item.totalPrice_acquistato.toString().replace(/\./g, ','); // Converti "." in ","
return [
0,
`"${item.name}"`,
item.weight,
formattedPrice,
item.totalQuantity,
total,
item.count
];
return [0, `"${item.name}"`, item.weight, formattedPrice, item.totalQuantity, total, item.count];
});
rows.unshift(headers);
const csvData = rows.map(row => row.join('|'));
const csvData = rows.map((row) => row.join('|'));
fs.writeFile(outputPath, csvData.join('\n'), (err) => {
if (err) {
@@ -778,8 +728,6 @@ function generateCSV(data, outputPath) {
});
}
// const Order = mongoose.model('Order', OrderSchema);
// module.exports = { Order };

View File

@@ -33,6 +33,7 @@ const OrdersCartSchema = new Schema({
totalQtyPreordered: { type: Number, default: 0 },
totalPrice: { type: Number, default: 0 },
totalPriceCalc: { type: Number, default: 0 },
totalPriceIntero: { type: Number, default: 0 },
department: {
type: String, ref: 'Department'
},
@@ -91,6 +92,12 @@ const OrdersCartSchema = new Schema({
note: {
type: String
},
codice_sconto: {
type: String
},
descr_sconto: {
type: String
},
note_per_gestore: {
type: String
},
@@ -568,11 +575,14 @@ module.exports.updateOrdersCartById = async function(id, newOrdersCart, callback
totalQtyPreordered: newOrdersCart.totalQtyPreordered,
totalPrice: newOrdersCart.totalPrice,
totalPriceCalc: newOrdersCart.totalPriceCalc ? newOrdersCart.totalPriceCalc : newOrdersCart.totalPrice,
totalPriceIntero: newOrdersCart.totalPriceIntero ? newOrdersCart.totalPriceIntero : newOrdersCart.totalPriceIntero,
userId: userId,
status: newOrdersCart.status,
numorder: newOrdersCart.numorder,
numord_pers: newOrdersCart.numord_pers,
note: newOrdersCart.note,
codice_sconto: newOrdersCart.codice_sconto,
descr_sconto: newOrdersCart.descr_sconto,
modify_at: new Date(),
}
},
@@ -1076,9 +1086,9 @@ module.exports.updateOrdersCartTotals = async function (idOrdersCart, update) {
let orderscart = await OrdersCart.getOrdersCartById(idOrdersCart);
if (orderscart) {
let newOrdersCart = CartClass.constructByCart(orderscart);
let newOrdersCart = await CartClass.constructByCart(orderscart);
newOrdersCart.updatecarttotals(false);
await newOrdersCart.updatecarttotals(false);
await newOrdersCart.updateExtraOrder();
if (update) {
@@ -1086,8 +1096,11 @@ module.exports.updateOrdersCartTotals = async function (idOrdersCart, update) {
$set: {
totalPrice: newOrdersCart.totalPrice,
totalPriceCalc: newOrdersCart.totalPriceCalc,
totalPriceIntero: newOrdersCart.totalPriceIntero,
totalQty: newOrdersCart.totalQty,
note: newOrdersCart.note,
codice_sconto: newOrdersCart.codice_sconto,
descr_sconto: newOrdersCart.descr_sconto,
modify_at: new Date(),
},
}

View File

@@ -29,6 +29,9 @@ const productSchema = new Schema({
idapp: {
type: String,
},
deleted: {
type: Boolean,
},
active: {
type: Boolean,
default: true,
@@ -164,6 +167,7 @@ const productSchema = new Schema({
maxbookableGASQty: {
// Quantità massima (ancora disponibile) Ordine GAS prenotabile (Complessivamente tra tutti gli ordini)
type: Number,
default: -1,
},
bookedGASQtyOrdered: {
// Quantità Ordine GAS Prenotate Totali
@@ -235,6 +239,18 @@ const productSchema = new Schema({
date_updated: {
type: Date,
},
scraped: {
type: Boolean,
},
scraped_error: {
type: Boolean,
},
scraped_updated: {
type: Boolean,
},
scraped_date: {
type: Date,
},
validaprod: {
esito: {
type: Number,
@@ -270,6 +286,8 @@ module.exports.executeQueryTable = function (idapp, params) {
module.exports.executeQueryPickup = async function (idapp, params) {
let strfindInput = tools.removeAccents(params.search.trim().toLowerCase());
strfindInput = strfindInput.replace(/#/g, ' '); // aggiungi spazio prima di # se vuoi conservarlo
// Rimuove le parole "il" e "la" e gli spazi, le @ e i tabulazioni
// per non farli influire sulla ricerca
strfindInput = strfindInput
@@ -292,7 +310,10 @@ module.exports.executeQueryPickup = async function (idapp, params) {
const cleanInput = tools.removeAccents(strfindInput.trim());
const words = cleanInput.split(/\s+/);
const escapeRegex = (w) => w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
const escapeRegex = (w) => {
// Escape del carattere '#' e altri caratteri speciali
return w.replace(/[.*+?^${}()|[\]\\]/g, '\\$&').replace(/#/g, '\\#');
};
// 🔹 Pattern per productInfo.name: tutte le parole devono essere presenti
const patternAllWords = words.map((w) => `(?=.*\\b${escapeRegex(w)})`).join('') + '.*';
@@ -419,6 +440,9 @@ module.exports.executeQueryPickup = async function (idapp, params) {
return [...risexact, ...ris];
};
module.exports.getProductByIsbn = function (idapp, isbn) {
return Product.findAllIdApp(idapp, null, null, null, isbn);
};
module.exports.getProductByCode = function (idapp, code) {
return Product.findAllIdApp(idapp, code);
};
@@ -451,7 +475,7 @@ module.exports.isLowQuantityInStockById = async function (id) {
return false;
};
module.exports.findAllIdApp = async function (idapp, code, id, all) {
module.exports.findAllIdApp = async function (idapp, code, id, all, isbn) {
let myfind = {};
let myqueryadd = {};
let query = [];
@@ -462,7 +486,10 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
}
if (idapp) {
myfind = { idapp };
myfind = {
idapp,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
};
}
if (!all) {
@@ -472,6 +499,9 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
if (code) {
myfind = { ...myfind, code };
}
if (isbn) {
myfind = { ...myfind, isbn };
}
if (id) {
myqueryadd = {
$addFields: {
@@ -585,7 +615,12 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
},
},
{ $unwind: { path: '$productInfo', preserveNullAndEmptyArrays: true } },
{
$match: {
'productInfo.code': { $exists: true, $ne: '' },
//'productInfo.imagefile': { $ne: 'noimg.jpg' },
},
},
{
$lookup: {
from: 'gasordines',

View File

@@ -6,6 +6,7 @@ const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
const { IImg } = require('../models/myscheda');
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
@@ -16,6 +17,9 @@ const productInfoSchema = new Schema({
idapp: {
type: String,
},
deleted: {
type: Boolean,
},
department: {
type: String, ref: 'Department'
},
@@ -206,7 +210,13 @@ module.exports.findAllIdApp = async function (idapp, code, id) {
try {
if (idapp)
myfind = { idapp };
myfind = {
idapp,
$or: [
{ deleted: { $exists: false } },
{ deleted: false }
]
};
if (code) {
myfind = { ...myfind, code }
@@ -520,6 +530,23 @@ module.exports.setImgNotFound = async function (id) {
}
// imposta tutti i record con image_not_found: false
module.exports.resetImageNotFound = async function () {
try {
const ProductInfo = this;
await ProductInfo.updateMany(
{ image_not_found: true },
{ $set: { image_not_found: false } }
);
console.log('Flag image_not_found reset to false for all records');
return true;
} catch (error) {
console.error('Error resetting image_not_found flag:', 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;
@@ -539,11 +566,17 @@ module.exports.removeProductInfoWithoutDateUpdatedFromGM = async function (idapp
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 });
await Product.updateMany(
{ idProductInfo: productinfo._id },
{ $set: { deleted: true } }
);
}
// Ora rimuovi anche questo productInfo
await ProductInfo.deleteOne({ _id: productinfo._id });
await ProductInfo.updateOne(
{ _id: productinfo._id },
{ $set: { deleted: true } }
);
}
}

View File

@@ -13,11 +13,12 @@ const { ObjectId } = require('mongodb');
const shared_consts = require('../tools/shared_nodejs');
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const ProvinceSchema = new Schema({
const ProvinceSchema = new Schema(
{
_id: {
type: Number,
},
@@ -29,6 +30,9 @@ const ProvinceSchema = new Schema({
// unique: true,
maxlength: 3,
},
idCircuitToAssign: {
type: String,
},
descr: {
type: String,
},
@@ -48,18 +52,16 @@ const ProvinceSchema = new Schema({
long: {
type: Number,
},
}, { _id: false });
},
{ _id: false }
);
ProvinceSchema.pre('save', async function (next) {
if (this.isNew) {
const myrec = await Province.findOne().limit(1).sort({ _id: -1 });
if (!!myrec) {
if (myrec._doc._id === 0)
this._id = 1;
else
this._id = myrec._doc._id + 1;
if (myrec._doc._id === 0) this._id = 1;
else this._id = myrec._doc._id + 1;
} else {
this._id = 1;
}
@@ -75,7 +77,7 @@ ProvinceSchema.statics.getRegionByStrProvince = async function (strprovince) {
}
return '';
}
};
ProvinceSchema.statics.getStrProvinceByProv = async function (prov) {
const myrec = await Province.findOne({ prov }).lean();
@@ -84,7 +86,7 @@ ProvinceSchema.statics.getStrProvinceByProv = async function (prov) {
}
return '';
}
};
ProvinceSchema.statics.getFieldsForSearch = function () {
return [
@@ -106,7 +108,6 @@ ProvinceSchema.statics.executeQueryTable = function (idapp, params) {
};
ProvinceSchema.statics.executeQueryPickup = async function (idapp, params) {
const strfind = params.search;
if (strfind === '') {
@@ -123,7 +124,6 @@ ProvinceSchema.statics.executeQueryPickup = async function (idapp, params) {
const ris = await Province.find(filterfind).lean().limit(10);
return [...risexact, ...ris];
};
ProvinceSchema.statics.findAllIdApp = async function (idapp) {
@@ -133,7 +133,6 @@ ProvinceSchema.statics.findAllIdApp = async function (idapp) {
};
ProvinceSchema.statics.setCoordinatesOnDB = async function () {
const arrprov = await Province.find({}).lean();
// Funzione per ottenere le coordinate di tutte le città
@@ -141,20 +140,23 @@ ProvinceSchema.statics.setCoordinatesOnDB = async function () {
if (!prov.lat) {
let coord = await tools.getCityCoordinates(prov);
if (coord) {
let ris = await Province.findOneAndUpdate({ _id: prov._id }, { $set: { lat: coord.lat, long: coord.long } }, { new: true });
let ris = await Province.findOneAndUpdate(
{ _id: prov._id },
{ $set: { lat: coord.lat, long: coord.long } },
{ new: true }
);
console.log(' *** Update ', prov.descr, 'lat', ris.lat, 'long', ris.long);
}
}
}
};
const Province = mongoose.model('Province', ProvinceSchema);
Province.createIndexes()
.then(() => {})
.catch((err) => { throw err; });
.catch((err) => {
throw err;
});
module.exports = { Province };

View File

@@ -0,0 +1,100 @@
const mongoose = require('mongoose').set('debug', false);
const Schema = mongoose.Schema;
const tools = require('../tools/general');
const { ObjectId } = require('mongodb');
const { IImg } = require('../models/myscheda');
mongoose.Promise = global.Promise;
mongoose.level = 'F';
// Resolving error Unknown modifier: $pushAll
mongoose.plugin((schema) => {
schema.options.usePushEach = true;
});
const RaccoltaCataloghiSchema = new Schema({
idapp: {
type: String,
},
active: {
type: Boolean,
default: false,
},
title: {
type: String,
index: true,
},
foto_raccolta: IImg,
idPageAssigned: {
type: String,
},
pdf_copertina: IImg,
nomefile_da_generare: String,
pdf_generato: String,
pdf_generato_size: String,
pdf_generato_stampa: String,
data_generato: {
type: Date,
},
data_generato_stampa: {
type: Date,
},
pdf_online: String,
pdf_online_size: String,
data_online: {
type: Date,
},
pdf_online_stampa: String,
pdf_online_stampa_size: String,
data_online_stampa: {
type: Date,
},
lista_cataloghi: [
{
type: Schema.Types.ObjectId,
ref: 'Catalog',
},
],
});
RaccoltaCataloghiSchema.statics.getFieldsForSearch = function () {
return [{ field: 'title', type: tools.FieldType.string }];
};
RaccoltaCataloghiSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
RaccoltaCataloghiSchema.statics.findAllIdApp = async function (idapp) {
const RaccoltaCataloghi = this;
try {
let arrrec = await RaccoltaCataloghi.find({ idapp }).sort({ title: 1 })
.populate({
path: 'lista_cataloghi',
select: '-lista_prodotti',
}).lean();
return arrrec;
} catch (err) {
console.error('Errore: ', err);
}
};
const RaccoltaCataloghi = mongoose.model('RaccoltaCataloghi', RaccoltaCataloghiSchema);
RaccoltaCataloghi.createIndexes()
.then(() => {})
.catch((err) => {
throw err;
});
module.exports = { RaccoltaCataloghi };

View File

@@ -16,6 +16,9 @@ const scontisticaSchema = new Schema({
idapp: {
type: String,
},
attivo: {
type: Boolean,
},
code: {
type: String,
},
@@ -31,6 +34,9 @@ const scontisticaSchema = new Schema({
price: {
type: Number,
},
applica: {
type: Number,
},
comulativo: {
type: Boolean,
default: false,
@@ -52,7 +58,7 @@ module.exports.executeQueryTable = function (idapp, params) {
};
module.exports.findAllIdApp = async function (idapp) {
const myfind = { idapp };
const myfind = { idapp, attivo: true };
return await Scontistica.find(myfind);
};

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
const mongoose = require('mongoose');
const { Schema } = mongoose;
mongoose.Promise = global.Promise;
mongoose.level = "F";
/**
* @typedef {Object} T_Web_Argomenti
* @property {bigint} Id
* @property {number} IdArgomento
* @property {string} Descrizione
* @property {Date} DataOra
* @property {boolean} Enabled
* @property {boolean} EnabledAlFresco
*/
const T_Web_ArgomentiSchema = new Schema({
IdArgomento: Number,
Descrizione: { type: String },
DataOra: Date,
Enabled: Boolean,
EnabledAlFresco: Boolean
}, { collection: 't_web_argomentis' });
const T_Web_Argomenti = module.exports = mongoose.model('T_Web_Argomenti', T_Web_ArgomentiSchema);
module.exports.findAllIdApp = async function () {
const myfind = {};
const myquery = [
{
$sort: { IdTipologia: 1, DataOra: -1 } // ordina per ID e DataOra decrescente
},
{
$group: {
_id: "$IdTipologia",
IdTipologia: { $first: "$IdTipologia" },
Descrizione: { $first: "$Descrizione" },
DataOra: { $first: "$DataOra" },
// aggiungi altri campi se servono
}
},
{
$sort: { IdTipologia: 1 } // opzionale, per ordinare il risultato
},
{
$project: {
_id: 0,
IdTipologia: 1,
Descrizione: 1
}
},
];
const rec = await T_Web_Argomenti.aggregate(myquery);
return rec;
};

View File

@@ -44,7 +44,16 @@ module.exports.findAllIdApp = async function () {
},
{
$sort: { IdStatoProdotto: 1 } // opzionale, per ordinare il risultato
},
{
$project: {
_id: 1,
IdStatoProdotto: 1,
Descrizione: 1
// rimuovi DataOra e aggiungi altri campi se servono
}
}
];
const rec = await T_WEB_StatiProdotto.aggregate(myquery);

View File

@@ -44,7 +44,14 @@ module.exports.findAllIdApp = async function () {
},
{
$sort: { IdTipoFormato: 1 } // opzionale, per ordinare il risultato
},
{
$project: {
_id: 0,
IdTipoFormato: 1,
Descrizione: 1,
}
},
];
const rec = await T_WEB_TipiFormato.aggregate(myquery);

View File

@@ -44,7 +44,15 @@ module.exports.findAllIdApp = async function () {
},
{
$sort: { IdTipologia: 1 } // opzionale, per ordinare il risultato
},
{
$project: {
_id: 0,
IdTipologia: 1,
Descrizione: 1
}
},
];
const rec = await T_WEB_Tipologie.aggregate(myquery);

File diff suppressed because it is too large Load Diff

View File

@@ -1,11 +1,14 @@
const shared_consts = require('../tools/shared_nodejs');
const cartModel = require('../models/cart')
const cartModel = require('../models/cart');
const { ObjectId } = require('mongodb');
const Gasordine = require('../models/gasordine');
const Order = require('../models/order');
const OrderClass = require('../modules/OrderClass');
const Scontistica = require('../models/scontistica');
class Cart {
constructor(order, arrorders) {
@@ -16,26 +19,53 @@ class Cart {
this.initializeFromOrder(order);
} else if (!!arrorders) {
for (const ord of arrorders) {
this.items.push(ord)
this.items.push(ord);
}
}
this.updatecarttotals(false);
}
async updatecarttotals(updateCalcPrice = true) {
try {
this.totalQty = 0;
this.totalPrice = 0;
this.totalPriceCalc = 0;
this.totalPriceIntero = 0;
for (const key in this.items) {
const item = this.items[key];
const order = item.order || item;
await this.updateOrderTotals(order, updateCalcPrice);
}
this.totalPrice = parseFloat(this.totalPrice.toFixed(2));
this.totalPriceCalc = parseFloat(this.totalPriceCalc.toFixed(2));
this.totalPriceIntero = parseFloat(this.totalPriceIntero.toFixed(2));
} catch (e) {
console.error("Errore durante l'aggiornamento del carrello:", e);
}
}
async init() {
await this.updatecarttotals(false);
}
initializeFromOrder(order) {
this.idapp = order.idapp || 0;
this.userId = order.userId || "";
this.userId = order.userId || '';
this.items[order._id] = order;
}
static constructByCart(cart) {
static async constructByCart(cart) {
try {
const mynewcart = new Cart(null);
await mynewcart.init();
mynewcart.idapp = cart.idapp || 0;
mynewcart.items = cart.items;
mynewcart.department = cart.department;
mynewcart.userId = cart.userId || "";
mynewcart.userId = cart.userId || '';
mynewcart.modify_at = new Date();
mynewcart.note_ordine_gas = '';
mynewcart.codice_sconto = cart.codice_sconto;
mynewcart.descr_sconto = cart.descr_sconto;
return mynewcart;
} catch (e) {
@@ -46,14 +76,14 @@ class Cart {
isAvailableByOrder(order) {
if (order && order.product) {
return (order.product.quantityAvailable > 0)
return order.product.quantityAvailable > 0;
}
return false;
}
isInPreorderByOrder(order) {
if (order && order.product) {
return (order.product.bookableAvailableQty > 0)
return order.product.bookableAvailableQty > 0;
}
return false;
}
@@ -61,48 +91,40 @@ class Cart {
isSameStorehouse(itemorder) {
try {
if (this.items.length > 0) {
const mystorehouse = this.items[0].order.idStorehouse
return (mystorehouse ? mystorehouse._id.toString() === itemorder.idStorehouse : true);
const mystorehouse = this.items[0].order.idStorehouse;
return mystorehouse ? mystorehouse._id.toString() === itemorder.idStorehouse : true;
} else {
return true;
}
} catch (e) {
return false;
}
}
async addqty(itemorder) {
const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id)
const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id);
if (!!myitem) {
let stepmin = myitem.order.product.minStepQty;
let stepmin = myitem.order?.product?.minStepQty || 1;
let step = stepmin;
if (this.isAvailableByOrder(myitem.order)) {
if (myitem.order.quantity === 0)
step = myitem.order.product.minBuyQty ?? stepmin
else if (myitem.order.quantity >= 10)
step = stepmin < 2 ? 2 : stepmin
else if (myitem.order.quantity >= 20)
step = stepmin < 5 ? 5 : stepmin
if (myitem.order.quantity === 0) step = myitem.order.product.minBuyQty ?? stepmin;
else if (myitem.order.quantity >= 10) step = stepmin < 2 ? 2 : stepmin;
else if (myitem.order.quantity >= 20) step = stepmin < 5 ? 5 : stepmin;
myitem.order.quantity += step;
} else {
if (myitem.order.quantitypreordered === 0)
step = myitem.order.product.minBuyQty ?? stepmin
else if (myitem.order.quantitypreordered >= 10)
step = stepmin < 2 ? 2 : stepmin
else if (myitem.order.quantitypreordered >= 20)
step = stepmin < 5 ? 5 : stepmin
if (myitem.order.quantitypreordered === 0) step = myitem.order.product.minBuyQty ?? stepmin;
else if (myitem.order.quantitypreordered >= 10) step = stepmin < 2 ? 2 : stepmin;
else if (myitem.order.quantitypreordered >= 20) step = stepmin < 5 ? 5 : stepmin;
myitem.order.quantitypreordered += step;
}
myitem.order.modify_at = new Date();
myitem.order = Order.updateTotals(myitem.order);
myitem.order = await Order.updateTotals(myitem.order, this.codice_sconto);
this.updatecarttotals(false);
await this.updatecarttotals(false);
await this.updateExtraOrder();
await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false });
return myitem.order;
@@ -110,27 +132,33 @@ class Cart {
}
qtaNextSub(myorder, myproduct) {
let step = myproduct.minStepQty
let minqta = myproduct.minBuyQty
try {
let step = myproduct.minStepQty || 1;
let minqta = myproduct.minBuyQty || 1;
if (myproduct.quantityAvailable > 0) {
if (myorder.quantity === minqta)
step = minqta
else {
if ((myorder.quantity - step) < 0)
step = myorder.quantity - step
if (myorder.quantity === minqta) {
step = minqta;
} else {
if (myorder.quantity - step < 0) {
step = myorder.quantity - step;
}
}
} else {
if (myorder.quantitypreordered === minqta)
step = minqta
if (myorder.quantitypreordered === minqta) {
step = minqta;
}
step = myorder.quantity - stepΩ;
}
return step;
} catch (e) {
console.error('Error in qtaNextSub: ', e);
return 0; // default step value in case of error
}
return step
}
async subqty(itemorder) {
try {
const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id)
const myitem = this.items.find((rec) => rec.order._id.toString() === itemorder._id);
if (!!myitem) {
let step = this.qtaNextSub(myitem.order, myitem.order.product);
if (myitem.order.quantitypreordered - step >= 0) {
@@ -140,8 +168,8 @@ class Cart {
myitem.order.quantity -= step;
}
}
myitem.order = Order.updateTotals(myitem.order);
this.updatecarttotals(false);
myitem.order = await Order.updateTotals(myitem.order, this.codice_sconto);
await this.updatecarttotals(false);
await this.updateExtraOrder();
await Order.findOneAndUpdate({ _id: myitem.order._id }, { $set: myitem.order }, { new: false });
@@ -152,15 +180,14 @@ class Cart {
}
}
async addItem(itemorder) {
// this.items.push(itemorder);
let ind = this.items.length;
this.items[ind] = {};
this.items[ind].order = itemorder;
this.items[ind].order = Order.updateTotals(this.items[ind].order);
this.updatecarttotals(false);
this.items[ind].order = await Order.updateTotals(this.items[ind].order, this.codice_sconto);
await this.updatecarttotals(false);
await this.updateExtraOrder();
return ind;
@@ -168,8 +195,8 @@ class Cart {
async removeItem(orderId) {
// this.items.push(itemorder);
this.items = this.items.filter(item => item.order._id.toString() !== orderId.toString());
this.updatecarttotals(false);
this.items = this.items.filter((item) => item.order._id.toString() !== orderId.toString());
await this.updatecarttotals(false);
await this.updateExtraOrder();
}
@@ -180,110 +207,75 @@ class Cart {
items: this.generateArray(),
totalQty: this.totalQty,
totalPriceCalc: this.totalPriceCalc,
totalPriceIntero: this.totalPriceIntero,
totalPrice: this.totalPrice,
userId: this.userId,
department: this.department,
note: this.note,
codice_sconto: this.codice_sconto,
descr_sconto: this.descr_sconto,
note_ordine_gas: this.note_ordine_gas,
modify_at: this.modify_at
})
return newCart
modify_at: this.modify_at,
});
return newCart;
} catch (e) {
console.error('Err', e);
}
return null;
}
updatecarttotals(updatecalcprice) {
try {
this.totalQty = 0;
this.totalPrice = 0;
this.totalPriceCalc = 0;
for (const rec in this.items) {
let mypricecalc = 0;
let order = this.items[rec].order;
if (!order) {
order = this.items[rec];
}
async updateOrderTotals(order, updateCalcPrice) {
order.TotalPriceProductCalc = 0;
if (updatecalcprice) {
// PROVO A METTERE SEMPRE CHE MI RICALCOLA IL PREZZO !
// updateCalcPrice = true;
if (updateCalcPrice) {
order.TotalPriceProduct = 0;
}
this.totalQty += order.quantity + order.quantitypreordered;
// Calcolo Sconto
let sconti_da_applicare = [];
if (order.scontisticas) {
const qty = order.quantity + order.quantitypreordered;
this.totalQty += qty;
let qtadascontare = order.quantity + order.quantitypreordered
let qtanonscontata = 0
const recscontisticheTrovate = await Cart.getRecSconto(this.idapp, this.codice_sconto, true);
while (qtadascontare > 0) {
let scontoapplicato = null
for (const sconto of order.scontisticas.filter((rec) => !rec.cumulativo)) {
if (qtadascontare >= sconto.qta) {
scontoapplicato = sconto
scontoapplicato.qtadascontare = sconto.qta
}
}
if (scontoapplicato && scontoapplicato.qtadascontare > 0) {
sconti_da_applicare.push(scontoapplicato)
qtadascontare -= scontoapplicato.qtadascontare
} else {
qtanonscontata = qtadascontare
qtadascontare = 0
}
}
const scontiDaUsare = recscontisticheTrovate?.length ? recscontisticheTrovate : order.scontisticas || [];
const priceCalc = this.calcolaPrezzoScontato(order, qty, scontiDaUsare);
const priceintero = this.calcolaPrezzoScontato(order, qty, []);
/*for (const sconto of order.scontisticas.filter((rec) => rec.cumulativo)) {
if ((sconto.qta % order.quantity) === 0) {
sconti_da_applicare.push(sconto)
}
}*/
order.TotalPriceProductCalc += priceCalc;
if (sconti_da_applicare.length > 0) {
for (const sconto of sconti_da_applicare) {
if (sconto.perc_sconto > 0) {
mypricecalc += (sconto.qtadascontare * order.price) * (1 - (sconto.perc_sconto / 100))
} else {
mypricecalc += sconto.price
}
}
}
if (qtanonscontata > 0) {
mypricecalc += order.price * qtanonscontata;
}
} else {
mypricecalc = (order.price * order.quantity) + (order.price * order.quantitypreordered);
}
// Aggiorna Totali
order.TotalPriceProductCalc += mypricecalc;
if (updatecalcprice) {
order.TotalPriceProduct += mypricecalc;
if (updateCalcPrice) {
order.TotalPriceProduct += priceCalc;
order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2));
}
// Qui lo calcolo sempre, anche se lo cambio manualmente
this.totalPriceCalc += mypricecalc;
this.totalPrice += order.TotalPriceProduct;
}
this.totalPrice = parseFloat(this.totalPrice.toFixed(2))
this.totalPriceCalc = parseFloat(this.totalPriceCalc.toFixed(2))
this.totalPriceCalc += priceCalc;
this.totalPriceIntero += priceintero;
} catch (e) {
console.error('Err: ', e);
// if (updateCalcPrice) {
// Aggiorna anche l'ordine associato
await Order.findOneAndUpdate({ _id: order._id }, { $set: order }, { new: false });
// }
}
calcolaPrezzoScontato(order, qtyTotale, sconti = []) {
if (!sconti || sconti.length === 0) {
return order.price * qtyTotale;
}
const { sconti_da_applicare, qtanonscontata } = OrderClass.applyNonCumulativeDiscounts(order, sconti);
const prezzoTotale = OrderClass.calculateDiscountedPrice(order, sconti_da_applicare, qtanonscontata);
return prezzoTotale;
}
async updateExtraOrder() {
try {
let arrGas = [];
const precnoteordgas = this.note_ordine_gas
const precnoteordgas = this.note_ordine_gas;
this.note_ordine_gas = '';
for (const rec in this.items) {
let order = this.items[rec].order;
@@ -296,8 +288,7 @@ class Cart {
if (recGas) {
if (recGas.note_ordine_gas) {
if (!arrGas.includes(recGas._id.toString())) {
if (this.note_ordine_gas)
this.note_ordine_gas += '<br>'
if (this.note_ordine_gas) this.note_ordine_gas += '<br>';
this.note_ordine_gas += '<strong>' + recGas.name + '</strong>' + ':<br>' + recGas.note_ordine_gas;
arrGas.push(recGas._id.toString());
@@ -306,7 +297,6 @@ class Cart {
}
}
}
} catch (e) {
console.error('Err:', e);
}
@@ -315,10 +305,57 @@ class Cart {
generateArray() {
let arr = [];
for (let id in this.items) {
arr.push(this.items[id])
arr.push(this.items[id]);
}
return arr;
}
static async getRecSconto(idapp, codice_sconto, soloAttivi) {
const condSconto = { $regex: new RegExp(`^${codice_sconto}$`, 'i') };
const query = {
idapp: idapp,
code: condSconto,
applica: shared_consts.SCONTI_APPLICA.A_TUTTI,
};
if (soloAttivi) {
query.attivo = true;
}
module.exports = Cart
const recscontisticheTrovate = await Scontistica.find(query).lean();
return recscontisticheTrovate;
}
async updateCartIntoDB() {
const result = await cartModel.updateCartByUserId(this.userId, {
items: this.items,
totalQty: this.totalQty,
totalPrice: this.totalPrice,
totalPriceCalc: this.totalPriceCalc,
totalPriceIntero: this.totalPriceIntero,
userId: this.userId,
});
return result;
}
async aggiornaCarrello() {
try {
// Rifai i calcoli !
await this.updatecarttotals(true);
await this.updateExtraOrder();
// Aggiorna i calcoli sul DB:
const mycart = await this.updateCartIntoDB();
// ritorna il carrello aggiornato !
return await cartModel.getCartCompletoByCartId(mycart._id, this.idapp);
} catch (e) {
console.error("Errore durante l'aggiornamento del carrello:", e);
}
}
}
module.exports = Cart;

View File

@@ -30,6 +30,7 @@ const { Circuit } = require('../models/circuit');
const { Province } = require('../models/province');
const { City } = require('../models/city');
const { Account } = require('../models/account');
const { Catalog } = require('../models/catalog');
const Macro = require('../modules/Macro');
@@ -37,54 +38,107 @@ class CronMod {
constructor() {}
async eseguiDbOp(idapp, mydata, req, res) {
let ris = await User.DbOp(idapp, mydata);
mydata.idapp = idapp;
const populate = require("../populate/populate");
const populate = require('../populate/populate');
const globalTables = require("../tools/globalTables");
const { Reaction } = require("../models/reaction");
const globalTables = require('../tools/globalTables');
const { Reaction } = require('../models/reaction');
let mystr = "";
const AmazonBookScraper = require('../modules/Scraping');
const GenPdf = require('../modules/GenPdf');
let mystr = '';
try {
if (mydata.dbop === "") {
if (mydata.dbop === '') {
// } else if (mydata.dbop === 'rigeneraTutto') {
// await ListaIngresso.Esegui_CronTab(idapp, mydata);
} else if (mydata.dbop === "ReplaceAllCircuits") {
} else if (mydata.dbop === 'ScraperMultipleDataAmazon') {
mystr = await AmazonBookScraper.ScraperMultipleDataAmazon(idapp, {
update: true,
aggiornasoloSeVuoti: true,
forzaricarica: false,
});
ris = { mystr };
} else if (mydata.dbop === 'ScraperEstraiDatiAmazon-NoUpdate') {
mystr = await AmazonBookScraper.ScraperMultipleDataAmazon(idapp, {
update: false,
aggiornasoloSeVuoti: false,
forzaricarica: true,
caricatutti: true,
});
ris = { mystr };
} else if (mydata.dbop === 'ScraperGeneraCSV') {
mystr = await AmazonBookScraper.ScraperGeneraCSV(idapp, mydata.options, res);
ris = { mystr };
} else if (mydata.dbop === 'removeDuplicateVariations') {
mystr = await AmazonBookScraper.removeDuplicateVariations(idapp, mydata.options);
ris = { mystr };
} else if (mydata.dbop === 'ScraperAzzeraFlagProducts') {
mystr = await AmazonBookScraper.ScraperAzzeraFlagProducts(idapp, mydata.options);
ris = { mystr };
} else if (mydata.dbop === 'GeneraPdfCatalogo') {
const genPdf = new GenPdf(idapp);
await genPdf.launch();
return await genPdf.generatePdfFromIdCatalog(mydata.options);
} else if (mydata.dbop === 'GeneraPdfRaccolta') {
const genPdf = new GenPdf(idapp);
await genPdf.launch();
return await genPdf.generatePdfFromIdRaccolta(mydata.options);
} else if (mydata.dbop === 'onlinePdfRaccolta') {
const genPdf = new GenPdf(idapp);
await genPdf.launch();
mydata.options.idapp = idapp;
return await genPdf.onlinePdfFromIdRaccolta(mydata.options);
} else if (mydata.dbop === 'ReplaceAllCircuits') {
// ++ Replace All Circuitname with 'Circuito RIS %s'
await Circuit.replaceAllCircuitNames(idapp);
} else if (mydata.dbop === "eliminaCatProds") {
} else if (mydata.dbop === 'eliminaCatProds') {
await CatProd.deleteMany({ idapp });
await SubCatProd.deleteMany({ idapp });
} else if (mydata.dbop === "removeProductInfoWithoutDateUpdatedFromGM") {
} else if (mydata.dbop === 'removeProductInfoWithoutDateUpdatedFromGM') {
mystr = await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(idapp);
ris = { mystr };
} else if (mydata.dbop === "StatMacro") {
} else if (mydata.dbop === 'resetImageNotFound') {
mystr = await ProductInfo.resetImageNotFound();
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
const { updateAllBook } = require("../controllers/articleController");
const { updateAllBook } = require('../controllers/articleController');
mystr = await updateAllBook(idapp, mydata.options);
ris = { mystr };
} else if (mydata.dbop === "updateAllBooksAndRemoveCanc") {
} else if (mydata.dbop === 'updateAllBooksAndRemoveCanc') {
// chiama updateAllBooksAndRemoveCanc
const { updateAllBook } = require("../controllers/articleController");
const { updateAllBook } = require('../controllers/articleController');
console.log('updateAllBooksAndRemoveCanc...');
mystr = await updateAllBook(idapp, {usaDBGMLocale: false, caricatutti: true, rimuovieventualiCancellati: true});
mystr = await updateAllBook(idapp, {
usaDBGMLocale: false,
caricatutti: true,
rimuovieventualiCancellati: true,
});
ris = { mystr };
} else if (mydata.dbop === "creaUtentiTest") {
} else if (mydata.dbop === 'creaUtentiTest') {
let num = 0;
lastrec = await User.find({ idapp }).sort({ _id: -1 }).limit(1);
let last = 1;
@@ -100,17 +154,17 @@ class CronMod {
myuser._id = new ObjectId();
myuser.index = last + ind + 1;
myuser.idapp = idapp;
myuser.password = "$2a$12$DEaX1h5saTUVC43f7kubyOAlah1xHDgqQTfSIux0.RFDT9WGbyCaG";
myuser.lang = "it";
myuser.email = "miaemail@email.it";
myuser.name = "U" + myuser.index;
myuser.surname = "Ar" + myuser.index;
myuser.password = '$2a$12$DEaX1h5saTUVC43f7kubyOAlah1xHDgqQTfSIux0.RFDT9WGbyCaG';
myuser.lang = 'it';
myuser.email = 'miaemail@email.it';
myuser.name = 'U' + myuser.index;
myuser.surname = 'Ar' + myuser.index;
myuser.verified_email = true;
myuser.verified_by_aportador = true;
if (myuser.index < 2) myuser.perm = "3";
myuser.username = "Userna_" + myuser.name;
if (myuser.index < 2) myuser.perm = '3';
myuser.username = 'Userna_' + myuser.name;
myuser.profile.special_req = true;
myuser.profile.nationality = "IT";
myuser.profile.nationality = 'IT';
await myuser.save();
num++;
}
@@ -139,57 +193,57 @@ class CronMod {
ris = { mystr };
*/
} else if (mydata.dbop === "CorreggiTabHours") {
} else if (mydata.dbop === 'CorreggiTabHours') {
ris = await Hours.correggiHours(idapp);
} else if (mydata.dbop === "setVerifiedByAportadorToALL") {
} else if (mydata.dbop === 'setVerifiedByAportadorToALL') {
ris = await User.setVerifiedByAportadorToALL();
} else if (mydata.dbop === "RewriteContribType") {
ris = populate.rewriteTable("contribtypes");
} else if (mydata.dbop === "ReplaceUsername") {
} else if (mydata.dbop === 'RewriteContribType') {
ris = populate.rewriteTable('contribtypes');
} else if (mydata.dbop === 'ReplaceUsername') {
if (User.isAdmin(req.user.perm)) {
ris = globalTables.replaceUsername(req.body.idapp, mydata.search_username, mydata.replace_username);
}
} else if (mydata.dbop === "ExitFromAllCircuitWithZero") {
} else if (mydata.dbop === 'ExitFromAllCircuitWithZero') {
if (User.isAdmin(req.user.perm)) {
ris = globalTables.ExitFromAllCircuitWithZero(req.body.idapp, mydata.search_username);
}
} else if (mydata.dbop === "replaceAportadorSolidario") {
} else if (mydata.dbop === 'replaceAportadorSolidario') {
if (User.isAdmin(req.user.perm)) {
ris = globalTables.replaceAportadorSolidario(req.body.idapp, mydata.search_username, mydata.replace_username);
}
} else if (mydata.dbop === "SearchString") {
} else if (mydata.dbop === 'SearchString') {
if (User.isAdmin(req.user.perm)) {
mystr = await globalTables.SearchString(req.body.idapp, mydata.search);
}
ris = { mystr };
} else if (mydata.dbop === "UpdateCatDeleteEmpty") {
} else if (mydata.dbop === 'UpdateCatDeleteEmpty') {
mystr = await CatProd.updateCatDeleteEmpty(req.body.idapp);
ris = { mystr };
} else if (mydata.dbop === "UpdateStatFatturato") {
} else if (mydata.dbop === 'UpdateStatFatturato') {
mystr = await ProductInfo.updateProductInfoByStats(req.body.idapp);
ris = { mystr };
} else if (mydata.dbop === "MigrateMSSQLToMongoDb") {
const { mssqlmigrateTables } = require("../controllers/articleController");
} else if (mydata.dbop === 'MigrateMSSQLToMongoDb') {
const { mssqlmigrateTables } = require('../controllers/articleController');
mystr = await mssqlmigrateTables(req);
ris = { mystr };
} else if (mydata.dbop === "copyFrom1To14") {
} else if (mydata.dbop === 'copyFrom1To14') {
const idapporig = 1;
const idappdest = 14;
if (!idapporig || !idappdest) return;
const globalTables = require("../tools/globalTables");
const globalTables = require('../tools/globalTables');
//++ Todo: TO FIXIT !
const mytablesstr = ["settings", "users", "templemail", "destnewsletter", "contribtypes", "bots", "cfgservers"];
const mytablesstr = ['settings', 'users', 'templemail', 'destnewsletter', 'contribtypes', 'bots', 'cfgservers'];
try {
let numrectot = 0;
for (const table of mytablesstr) {
const mytable = globalTables.getTableByTableName(table);
tools.mylogshow("copyfromapptoapp: ", table, mytable);
tools.mylogshow('copyfromapptoapp: ', table, mytable);
await mytable.DuplicateAllRecords(idapporig, idappdest).then((numrec) => {
// tools.mylogshow(' REC TO MODIFY: ', rec);
@@ -199,40 +253,40 @@ class CronMod {
ris = true;
} catch (e) {
console.log("e", e);
console.log('e', e);
}
} else if (mydata.dbop === "removeRecordsFav") {
} else if (mydata.dbop === 'removeRecordsFav') {
// Passa le tabelle da users sulle nuove tabelle:
await User.removerecordsFavorite();
} else if (mydata.dbop === "updateReactionsCounts") {
} else if (mydata.dbop === 'updateReactionsCounts') {
await Reaction.updateReactionsCounts();
} else if (mydata.dbop === "GeneraCSVOrdineProdotti") {
} else if (mydata.dbop === 'GeneraCSVOrdineProdotti') {
await Order.GeneraCSVOrdineProdotti();
} else if (mydata.dbop === "RemoveDeletedOrdersInOrderscart") {
} else if (mydata.dbop === 'RemoveDeletedOrdersInOrderscart') {
await Order.RemoveDeletedOrdersInOrderscart();
} else if (mydata.dbop === "CheckTransazioniCircuiti") {
} else if (mydata.dbop === 'CheckTransazioniCircuiti') {
await Circuit.CheckTransazioniCircuiti(false);
} else if (mydata.dbop === "CorreggiTransazioniCircuiti") {
} else if (mydata.dbop === 'CorreggiTransazioniCircuiti') {
await Circuit.CheckTransazioniCircuiti(true);
} else if (mydata.dbop === "RemovePendentTransactions") {
} else if (mydata.dbop === 'RemovePendentTransactions') {
ris = await SendNotif.RemovePendentTransactions(idapp);
} else if (mydata.dbop === "RemoveOldNotif90") {
} else if (mydata.dbop === 'RemoveOldNotif90') {
await SendNotif.RemoveOldNotif90(idapp);
} else if (mydata.dbop === "RemoveOldNotif30") {
} else if (mydata.dbop === 'RemoveOldNotif30') {
await SendNotif.RemoveOldNotif30(idapp);
} else if (mydata.dbop === "UpdateCoordProv") {
} else if (mydata.dbop === 'UpdateCoordProv') {
await Province.setCoordinatesOnDB();
} else if (mydata.dbop === "insertGeojsonToMongoDB") {
await City.insertGeojsonToMongoDB("comuni_italia.geojson");
} else if (mydata.dbop === "listCollectionsBySize") {
} else if (mydata.dbop === 'insertGeojsonToMongoDB') {
await City.insertGeojsonToMongoDB('comuni_italia.geojson');
} else if (mydata.dbop === 'listCollectionsBySize') {
mystr = await tools.listCollectionsBySize();
ris = { mystr };
} else if (mydata.dbop === "EnableNewsOn_ToAll") {
} 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);
ris = { mystr };
} else if (mydata.dbop === "AbilitaNewsletterALL") {
} else if (mydata.dbop === 'AbilitaNewsletterALL') {
await User.updateMany(
{
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
@@ -240,44 +294,44 @@ class CronMod {
{ $set: { news_on: true } },
{ new: false }
);
} else if (mydata.dbop === "SvuotaTuttiGliAccessiOnlineConToken") {
} else if (mydata.dbop === 'SvuotaTuttiGliAccessiOnlineConToken') {
await User.SvuotaTuttiGliAccessiOnlineConToken(idapp);
} else if (mydata.dbop === "SettaAdTypeOffro_In_Hosps") {
const { MyHosp } = require("../models/myhosp");
} else if (mydata.dbop === 'SettaAdTypeOffro_In_Hosps') {
const { MyHosp } = require('../models/myhosp');
await MyHosp.SettaAdTypeOffro_In_Hosps(idapp);
} else if (mydata.dbop === "removeRegulations") {
await Circuit.updateMany({}, { $set: { regulation: "" } });
} else if (mydata.dbop === "newRecordsFav") {
} else if (mydata.dbop === 'removeRegulations') {
await Circuit.updateMany({}, { $set: { regulation: '' } });
} else if (mydata.dbop === 'newRecordsFav') {
// Passa le tabelle da users sulle nuove tabelle:
await User.moverecordsFavorite(1);
await User.moverecordsFavorite(2);
await User.moverecordsFavorite(3);
await User.moverecordsFavorite(4);
await User.moverecordsFavorite(5);
} else if (mydata.dbop === "emptyTabCatServiziBeni") {
const { Sector } = require("../models/sector");
const { SectorGood } = require("../models/sectorgood");
const { Skill } = require("../models/skill");
const { Good } = require("../models/good");
} else if (mydata.dbop === 'emptyTabCatServiziBeni') {
const { Sector } = require('../models/sector');
const { SectorGood } = require('../models/sectorgood');
const { Skill } = require('../models/skill');
const { Good } = require('../models/good');
await Sector.deleteMany({});
await SectorGood.deleteMany({});
await Skill.deleteMany({});
ris = await Good.deleteMany({});
} else if (mydata.dbop === "emptyDbSkill") {
} else if (mydata.dbop === 'emptyDbSkill') {
// Svuota e Ricrea
const { Sector } = require("../models/sector");
const { SectorGood } = require("../models/sectorgood");
const { Skill } = require("../models/skill");
const { Good } = require("../models/good");
const { SubSkill } = require("../models/subskill");
const { Contribtype } = require("../models/contribtype");
const { AdType } = require("../models/adtype");
const { AdTypeGood } = require("../models/adtypegood");
const { StatusSkill } = require("../models/statusSkill");
const { CatGrp } = require("../models/catgrp");
const { Sector } = require('../models/sector');
const { SectorGood } = require('../models/sectorgood');
const { Skill } = require('../models/skill');
const { Good } = require('../models/good');
const { SubSkill } = require('../models/subskill');
const { Contribtype } = require('../models/contribtype');
const { AdType } = require('../models/adtype');
const { AdTypeGood } = require('../models/adtypegood');
const { StatusSkill } = require('../models/statusSkill');
const { CatGrp } = require('../models/catgrp');
await Sector.deleteMany({});
await SectorGood.deleteMany({});
@@ -291,19 +345,19 @@ class CronMod {
await CatGrp.deleteMany({});
ris = await populate.popolaTabelleNuove();
} else if (mydata.dbop === "ricreaTabCitiesProvinces") {
} else if (mydata.dbop === 'ricreaTabCitiesProvinces') {
// Svuota e Ricrea
const { City } = require("../models/city");
const { Province } = require("../models/province");
const { City } = require('../models/city');
const { Province } = require('../models/province');
await City.deleteMany({});
await Province.deleteMany({});
ris = await populate.popolaTabelleNuove();
} else if (mydata.dbop === "PopulateTables") {
} else if (mydata.dbop === 'PopulateTables') {
ris = populate.popolaTabelleNuove();
} else if (mydata.dbop === "dropProducts") {
} else if (mydata.dbop === 'dropProducts') {
if (idapp) {
const deleteProducts = await Product.deleteMany({ idapp });
console.log(`Cancellati ${deleteProducts.deletedCount} record dalla collezione Product.`);
@@ -314,11 +368,11 @@ class CronMod {
}
ris = deleteProductInfo ? true : false;
} else if (mydata.dbop === "dropCatProd") {
} else if (mydata.dbop === 'dropCatProd') {
const deleteCatProd = await CatProd.deleteMany({ idapp });
} else if (mydata.dbop === "dropSubCatProd") {
} else if (mydata.dbop === 'dropSubCatProd') {
const deleteSubCatProd = await SubCatProd.deleteMany({ idapp });
} else if (mydata.dbop === "dropAllOrders") {
} else if (mydata.dbop === 'dropAllOrders') {
try {
const deleteOrder = await Order.deleteMany({ idapp });
const deleteOrdersCart = await OrdersCart.deleteMany({ idapp });
@@ -326,9 +380,9 @@ class CronMod {
ris = deleteCart;
} catch (e) {
console.error("Err:", e);
console.error('Err:', e);
}
} else if (mydata.dbop === "SistemaGasOrdine") {
} else if (mydata.dbop === 'SistemaGasOrdine') {
const arrrec = await Product.find({}).lean();
for (const rec of arrrec) {
if (tools.isArray(rec.idGasordines) && rec.idGasordines.length > 0) {
@@ -337,7 +391,7 @@ class CronMod {
await Product.findByIdAndUpdate(rec._id, { $set: { idGasordine: null } });
}
}
} else if (mydata.dbop === "CopyPriceToCalc") {
} else if (mydata.dbop === 'CopyPriceToCalc') {
try {
const arrrec = await OrdersCart.find({}).lean();
for (const rec of arrrec) {
@@ -349,30 +403,30 @@ class CronMod {
await Order.findByIdAndUpdate(rec._id, { $set: { TotalPriceProductCalc: rec.TotalPriceProduct } });
}
} catch (e) {
console.error("Err:", e);
console.error('Err:', e);
}
} else if (mydata.dbop === "dropAllCarts") {
} else if (mydata.dbop === 'dropAllCarts') {
ris = await Cart.deleteMany({ idapp });
} else if (mydata.dbop === "RewriteCitiesTable") {
ris = populate.rewriteTable("cities");
} else if (mydata.dbop === "RewriteLevelsTable") {
ris = populate.rewriteTable("levels");
} else if (mydata.dbop === "RewriteProvincesTable") {
ris = populate.rewriteTable("provinces");
} else if (mydata.dbop === "emptyCityProvinces") {
const { City } = require("../models/city");
const { Province } = require("../models/province");
} else if (mydata.dbop === 'RewriteCitiesTable') {
ris = populate.rewriteTable('cities');
} else if (mydata.dbop === 'RewriteLevelsTable') {
ris = populate.rewriteTable('levels');
} else if (mydata.dbop === 'RewriteProvincesTable') {
ris = populate.rewriteTable('provinces');
} else if (mydata.dbop === 'emptyCityProvinces') {
const { City } = require('../models/city');
const { Province } = require('../models/province');
await City.deleteMany({});
await Province.deleteMany({});
} else if (mydata.dbop === "ConvTablesFromIntToString") {
const { MySkill } = require("../models/myskill");
const { MyBacheca } = require("../models/mybacheca");
const { MyHosp } = require("../models/myhosp");
const { MyGood } = require("../models/mygood");
} else if (mydata.dbop === 'ConvTablesFromIntToString') {
const { MySkill } = require('../models/myskill');
const { MyBacheca } = require('../models/mybacheca');
const { MyHosp } = require('../models/myhosp');
const { MyGood } = require('../models/mygood');
// const { MyGroup } = require('../models/mygroup');
console.log("INIZIO - Conversioni");
console.log('INIZIO - Conversioni');
// 'myskills',
// 'mybachecas',
// 'myhosps',
@@ -385,15 +439,15 @@ class CronMod {
await ConvertiDaIntAStr(MyGood);
await ConvertiDaIntAStr(MyGroup);
console.log("FINE - Conversioni");
} else if (mydata.dbop === "Removeinteger") {
const { MySkill } = require("../models/myskill");
const { MyBacheca } = require("../models/mybacheca");
const { MyHosp } = require("../models/myhosp");
const { MyGood } = require("../models/mygood");
console.log('FINE - Conversioni');
} else if (mydata.dbop === 'Removeinteger') {
const { MySkill } = require('../models/myskill');
const { MyBacheca } = require('../models/mybacheca');
const { MyHosp } = require('../models/myhosp');
const { MyGood } = require('../models/mygood');
// const { MyGroup } = require('../models/mygroup');
console.log("INIZIO - Rimozione");
console.log('INIZIO - Rimozione');
await RimuoviInteri(MySkill);
await RimuoviInteri(MyBacheca);
@@ -401,45 +455,45 @@ class CronMod {
await RimuoviInteri(MyGood);
await RimuoviInteri(MyGroup);
console.log("FINE - Rimozione");
} else if (mydata.dbop === "createAllCircuits") {
const { Province } = require("../models/province");
console.log('FINE - Rimozione');
} else if (mydata.dbop === 'createAllCircuits') {
const { Province } = require('../models/province');
const arrProv = await Province.find({});
for (const recprov of arrProv) {
await Circuit.createCircuitIfNotExist(req, idapp, recprov.prov);
}
} else if (mydata.dbop === "correggiProductTypes") {
} else if (mydata.dbop === 'correggiProductTypes') {
await ProductInfo.correggiProductTypes();
} else if (mydata.dbop === "replaceProductImgToImageFile") {
} else if (mydata.dbop === 'replaceProductImgToImageFile') {
await ProductInfo.replaceProductImgToImageFile(true);
} else if (mydata.dbop === "removeUploadProducts_Path") {
} else if (mydata.dbop === 'removeUploadProducts_Path') {
await ProductInfo.replaceProductImgToImageFile(false);
} else if (mydata.dbop === "correggiCircuitiANull") {
await User.updateMany({}, { $pull: { "profile.mycircuits": { circuitname: null } } });
} else if (mydata.dbop === "ImpostaMinMaxPersonali") {
await Account.SetMinMaxPersonali(idapp, mydata.valmin, mydata.valmax, "");
} else if (mydata.dbop === "ImpostaMinMaxPersonaliCircuito") {
} else if (mydata.dbop === 'correggiCircuitiANull') {
await User.updateMany({}, { $pull: { 'profile.mycircuits': { circuitname: null } } });
} else if (mydata.dbop === 'ImpostaMinMaxPersonali') {
await Account.SetMinMaxPersonali(idapp, mydata.valmin, mydata.valmax, '');
} else if (mydata.dbop === 'ImpostaMinMaxPersonaliCircuito') {
await Account.SetMinMaxPersonali(idapp, mydata.valmin, mydata.valmax, mydata.circuitId);
} else if (mydata.dbop === "ImpostaMinMaxComunitari") {
} else if (mydata.dbop === 'ImpostaMinMaxComunitari') {
await Account.SetMinMaxComunitari(idapp, mydata.valmin, mydata.valmax);
} else if (mydata.dbop === "ImpostaMinMaxCollettivi") {
} else if (mydata.dbop === 'ImpostaMinMaxCollettivi') {
await Account.SetMinMaxCollettivi(idapp, mydata.valmin, mydata.valmax);
} else if (mydata.dbop === "ImpostaDefMinMaxPersonali") {
} else if (mydata.dbop === 'ImpostaDefMinMaxPersonali') {
await Circuit.SetDefMinMaxPersonali(idapp, mydata.valmin, mydata.valmax, mydata.circuitId);
} else if (mydata.dbop === "ImpostaDefMinMaxCollettivi") {
} else if (mydata.dbop === 'ImpostaDefMinMaxCollettivi') {
await Circuit.SetDefMinMaxCollettivi(idapp, mydata.valmin, mydata.valmax, mydata.circuitId);
} else if (mydata.dbop === "AbilitaTuttiCircuiti") {
} else if (mydata.dbop === 'AbilitaTuttiCircuiti') {
await Circuit.AbilitaTuttiCircuiti(idapp);
} else if (mydata.dbop === "AzzeraRegolamentiTuttiCircuiti") {
} else if (mydata.dbop === 'AzzeraRegolamentiTuttiCircuiti') {
await Circuit.AzzeraRegolamentiTuttiCircuiti(idapp);
} else if (mydata.dbop === "setstrProvByIdCityCircuits") {
} else if (mydata.dbop === 'setstrProvByIdCityCircuits') {
await Circuit.setstrProvByIdCityCircuits(idapp);
} else if (mydata.dbop === "updateSaldoAndTransato_AllAccounts") {
} else if (mydata.dbop === 'updateSaldoAndTransato_AllAccounts') {
await Account.updateSaldoAndTransato_AllAccounts(idapp);
} else if (mydata.dbop === "generateBotMenuRecords") {
} else if (mydata.dbop === 'generateBotMenuRecords') {
await MyBot.generateBotMenuRecords(idapp);
} else if (mydata.dbop === "GenerateVapiKey") {
} else if (mydata.dbop === 'GenerateVapiKey') {
await tools.generateVapiKey();
/*} else if (mydata.dbop === 'visuNave') {

View File

@@ -0,0 +1,633 @@
const puppeteer = require('puppeteer');
const path = require('path');
const { exec } = require('child_process');
const fs = require('fs').promises;
const gs = require('ghostscript4js');
const { PDFDocument, rgb } = require('pdf-lib');
const { Catalog } = require('../models/catalog');
const { MyPage } = require('../models/mypage');
const tools = require('../tools/general');
const shared_consts = require('../tools/shared_nodejs');
const { compress } = require('compress-pdf');
const { RaccoltaCataloghi } = require('../models/raccoltacataloghi');
class GenPdf {
constructor(idapp) {
this.idapp = idapp;
this.browser = null;
}
async launch() {
this.browser = await puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
}
async close() {
if (this.browser) {
await this.browser.close();
this.browser = null;
}
}
inchesToPixels(inches, stampa) {
if (stampa) {
return Math.floor(inches * 300);
} else {
return Math.floor(inches * 96);
}
}
mmToInches(mm) {
return mm / 25.4;
}
async autoScroll(page) {
console.log('inizia a scrollare...');
// Esegui lo scroll fino a quando tutta la pagina non è stata scrollata
await page.evaluate(async () => {
await new Promise((resolve) => {
let totalHeight = 0;
const distance = 100; // distanza dello scroll ad ogni intervallo
const delay = 40; // tempo di intervallo in ms
const scroll = async () => {
// Esegui lo scroll
window.scrollBy(0, distance);
totalHeight += distance;
// Verifica se è stato scrollato tutto il corpo della pagina
if (totalHeight < document.body.scrollHeight) {
setTimeout(scroll, delay); // Se non è finito lo scroll, continua
} else {
resolve(); // Scroll terminato
}
};
scroll(); // Avvia lo scroll
});
});
}
async generatePdfFromUrl(url, filenameOut, options = {}) {
if (!this.browser) {
throw new Error('Browser non avviato. Chiama launch() prima.');
}
const page = await this.browser.newPage();
const maxTentativi = 3;
try {
console.log(`caricamento pagina: ${url}`);
await page.goto(url, { waitUntil: 'networkidle0' });
await page.waitForNavigation({ waitUntil: 'networkidle0' }).catch(() => {});
page.on('console', (msg) => {
if (msg.type() === 'error') {
console.error('Errore nella pagina:', msg.text());
}
});
await tools.attendiNSecondi(6);
let success = false;
let numTentativi1 = 0;
console.log(`Cerco .pdf-section...`);
while (numTentativi1 < maxTentativi) {
try {
await page.waitForSelector('.pdf-section', { timeout: 10000 });
console.log(` .pdf-section trovato !...`);
success = true;
break;
} catch (e) {
console.log(`Tentativo ${numTentativi1 + 1}/${maxTentativi} fallito, ASPETTO DI PIU 10 secondi`);
await tools.attendiNSecondi(10);
}
numTentativi1++;
}
await this.autoScroll(page);
await tools.attendiNSecondi(5);
// Seleziona tutte le sezioni da stampare
let sectionHandles = await page.$$('.pdf-section');
let numTentativi = 0;
while (sectionHandles.length === 0 && numTentativi < maxTentativi) {
console.log(
`Nessuna sezione .pdf-section trovata nella pagina, quindi ASPETTO DI PIU ${numTentativi + 1}/${maxTentativi}`
);
await tools.attendiNSecondi(5);
sectionHandles = await page.$$('.pdf-section');
numTentativi++;
}
if (sectionHandles.length === 0) {
throw new Error(`Nessuna sezione .pdf-section trovata nella pagina dopo ${maxTentativi} tentativi`);
}
const pdfBuffers = [];
for (const sectionHandle of sectionHandles) {
// Nascondi tutte le sezioni
await page.evaluate(() => {
document.querySelectorAll('.pdf-section').forEach((el) => (el.style.display = 'none'));
});
// Mostra solo la sezione corrente
await sectionHandle.evaluate((el) => (el.style.display = 'block'));
// Calcola dimensioni della sezione
const { width, height } = await sectionHandle.evaluate((el) => ({
width: el.scrollWidth, // piccolo padding
height: el.scrollHeight, // piccolo padding
}));
// console.log(`Larghezza: ${width}px, Altezza: ${height}px`);
// Imposta viewport dinamico
await page.setViewport({ width, height });
// Genera pdf buffer per questa pagina
const pdfBuffer = await page.pdf({
printBackground: true,
width: `${width}px`,
height: `${height}px`,
margin: { top: '0', bottom: '0', left: '0', right: '0' },
});
pdfBuffers.push(pdfBuffer);
}
// Unisci tutti i PDF
const mergedPdf = await PDFDocument.create();
for (const pdfBytes of pdfBuffers) {
const pdf = await PDFDocument.load(pdfBytes);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => mergedPdf.addPage(page));
}
const mergedPdfFile = await mergedPdf.save();
const finalFilePath = path.resolve(process.cwd(), filenameOut);
await fs.writeFile(finalFilePath, mergedPdfFile);
// Ripristina tutte le sezioni visibili
await page.evaluate(() => {
document.querySelectorAll('.pdf-section').forEach((el) => (el.style.display = 'block'));
});
console.log(`PDF finale generato: ${finalFilePath}`);
return finalFilePath;
} catch (error) {
console.error('Errore durante generazione PDF:', error);
throw error;
} finally {
await page.close();
}
}
async convertPDF_ChildProcess(inputFile, outputFile, widthpx, heightpx, compressionLevel = 'screen') {
const { spawn } = require('child_process');
const path = require('path');
widthpx = widthpx * 2;
heightpx = heightpx * 2;
console.log('=== CONVERSIONE CON CHILD_PROCESS E COMPRESSIONE ===');
// Verifica input
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`File input non trovato: ${inputFile}`);
}
// Assicurati che la directory output esista
const outputDir = path.dirname(outputFile);
try {
await fs.mkdir(outputDir, { recursive: true });
} catch (error) {
// Directory già esistente, ok
}
// Parametri di compressione ottimizzati
const compressionSettings = {
/*maximum: [
'-dPDFSETTINGS=/screen',
'-dDownsampleColorImages=true',
'-dColorImageResolution=72',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=72',
'-dDownsampleMonoImages=true',
'-dMonoImageResolution=72',
],
high: [
'-dPDFSETTINGS=/ebook',
'-dDownsampleColorImages=true',
'-dColorImageResolution=150',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=150',
],*/
printer: ['-dPDFSETTINGS=/printer', '-dDownsampleColorImages=true', '-dColorImageResolution=300'],
screen: [
'-dPDFSETTINGS=/screen',
'-dDownsampleColorImages=true',
'-dColorImageResolution=96',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=96',
],
};
return new Promise((resolve, reject) => {
const args = [
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
'-dSAFER',
// Parametri di compressione
...(compressionSettings[compressionLevel] || compressionSettings['screen']),
'-dCompressFonts=true',
'-dSubsetFonts=true',
'-dColorImageFilter=/DCTEncode',
'-dGrayImageFilter=/DCTEncode',
'-dEmbedAllFonts=true',
// Dimensioni pagina
`-g${widthpx}x${heightpx}`,
'-dFIXEDMEDIA',
// '-dPDFFitPage',
// Output
`-sOutputFile=${outputFile}`,
inputFile,
];
console.log('Spawning gs with compression args:', args.join(' '));
const gsProcess = spawn('gs', args, {
stdio: ['ignore', 'pipe', 'pipe'],
shell: process.platform === 'win32',
});
let stdout = '';
let stderr = '';
gsProcess.stdout.on('data', (data) => {
stdout += data.toString();
if (stdout.length < 1000) {
// Evita log troppo lunghi
console.log('GS OUT:', data.toString().trim());
}
});
gsProcess.stderr.on('data', (data) => {
stderr += data.toString();
if (stderr.length < 1000) {
console.log('GS ERR:', data.toString().trim());
}
});
gsProcess.on('close', async (code) => {
console.log(`GS process closed with code: ${code}`);
if (code === 0) {
// Attendi e verifica
setTimeout(async () => {
try {
const exists = await tools.isFileExistsAsync(outputFile);
if (exists) {
// Verifica dimensioni per confermare compressione
try {
const originalStats = await tools.getFileStatsAsync(inputFile);
const newStats = await tools.getFileStatsAsync(outputFile);
const compressionRatio = (((originalStats.size - newStats.size) / originalStats.size) * 100).toFixed(
1
);
console.log(`📁 File originale: ${(originalStats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`📁 File compresso: ${(newStats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`🗜️ Compressione: ${compressionRatio}%`);
console.log('✅ SUCCESS: File generato e compresso');
} catch (statsError) {
console.log('Warning: impossibile calcolare statistiche compressione');
}
resolve(outputFile);
} else {
console.log('❌ FAIL: File non generato nonostante exit code 0');
reject(new Error('File non generato nonostante successo processo'));
}
} catch (error) {
reject(error);
}
}, 1000);
} else {
reject(new Error(`Ghostscript failed with code ${code}: ${stderr}`));
}
});
gsProcess.on('error', (error) => {
console.log('GS process error:', error);
reject(new Error(`Failed to start Ghostscript: ${error.message}`));
});
});
}
async generatePdfFromUrls(urls, outputFilename) {
if (!this.browser) {
throw new Error('Browser non avviato. Chiama launch() prima.');
}
const pdfBuffers = [];
outputFilename = tools.getdirByIdApp(idapp) + '/';
try {
for (const url of urls) {
// ............
}
const mergedPdf = await PDFDocument.create();
for (const pdfBytes of pdfBuffers) {
const pdf = await PDFDocument.load(pdfBytes);
const copiedPages = await mergedPdf.copyPages(pdf, pdf.getPageIndices());
copiedPages.forEach((page) => mergedPdf.addPage(page));
}
const mergedPdfFile = await mergedPdf.save();
const outputPath = path.resolve(process.cwd(), outputFilename);
await fs.writeFile(outputPath, mergedPdfFile);
console.log(`PDF unito generato: ${outputPath}`);
return outputPath;
} catch (error) {
console.error('Errore durante la generazione PDF:', error);
throw error;
}
}
async getPathByPage(idpage) {
const mypage = await MyPage.findById(idpage);
if (mypage) {
return mypage.path;
}
return '';
}
async generatePdfFromIdRaccolta(options) {
try {
if (!options) {
console.error('Opzioni non passate !');
return null;
}
const raccolta = await RaccoltaCataloghi.findById(options.idRaccolta);
if (raccolta) {
for (const catalogo of raccolta.lista_cataloghi) {
await this.generatePdfFromIdCatalog({
...options,
idCatalog: catalogo._id,
});
}
}
} catch (e) {
console.error('err', e);
}
}
async onlinePdfFromIdRaccolta(options) {
try {
if (!options) {
console.error('Opzioni non passate !');
return null;
}
const raccolta = await RaccoltaCataloghi.findById(options.idRaccolta);
if (raccolta) {
console.log('Pubblica ONLINE la Raccolta ' + raccolta.title + ' ...');
for (const catalogo of raccolta.lista_cataloghi) {
await this.onlinePdfFromIdCatalog({
...options,
id_catalog: catalogo._id,
});
}
console.log('FINE Pubblicazione ONLINE !');
}
} catch (e) {
console.error('err', e);
}
}
async onlinePdfFromIdCatalog(options) {
const risout = await this.onlinePdf(options);
}
async generatePdfFromIdCatalog(options) {
try {
if (!options) {
console.error('Opzioni non passate !');
return null;
}
let filenamerelative = '';
let fullnamepath = '';
let fullnamepath_compr = '';
let filenamerelative_compressed = '';
let stampa = options.stampa;
/*if (stampa) {
options.width = '227.3mm';
options.height = '313.5mm';
} else {
options.width = '210mm';
options.height = '297mm';
}*/
const catalog = await Catalog.findById(options.idCatalog);
if (catalog) {
const myfilenameout = await this.getPathByPage(catalog.idPageAssigned);
const url =
tools.getHostByIdApp(this.idapp) +
'/' +
myfilenameout +
'?' +
'stampa=' +
(stampa ? '1' : '0') +
'&hideHeader=1';
if (url) {
let addstr = stampa ? '_stampabile' : '';
filenamerelative = options.path + `${myfilenameout}${addstr}_generato.pdf`;
fullnamepath = tools.getdirByIdApp(this.idapp) + '/' + filenamerelative;
await this.generatePdfFromUrl(url, fullnamepath, options);
if (options.comprimi) {
filenamerelative_compressed = options.path + `${myfilenameout}${addstr}_generato_compressed.pdf`;
fullnamepath_compr = tools.getdirByIdApp(this.idapp) + '/' + filenamerelative_compressed;
await this.compressPdf(fullnamepath, fullnamepath_compr, options.compressione);
}
}
}
const ris = {
fileout: filenamerelative,
fileout_compressed: filenamerelative_compressed,
filesize: await tools.getSizeFile(fullnamepath),
filesize_compressed: await tools.getSizeFile(fullnamepath_compr),
error: '',
};
if (catalog) {
if (stampa) {
catalog.pdf_generato_stampa = ris.fileout;
catalog.pdf_generato_stampa_compressed = ris.fileout_compressed;
catalog.pdf_generato_stampa_size = ris.filesize;
catalog.pdf_generato_stampa_compr_size = ris.filesize_compressed;
catalog.data_generato_stampa = tools.getDateNow();
} else {
catalog.pdf_generato_compressed = ris.fileout_compressed;
catalog.pdf_generato = ris.fileout;
catalog.pdf_generato_size = ris.filesize;
catalog.pdf_generato_compr_size = ris.filesize_compressed;
catalog.data_generato = tools.getDateNow();
}
await catalog.save();
}
return ris;
} catch (error) {
console.error('Errore durante la generazione del PDF dal catalogo ID:', error);
return {
fileout: '',
filesize: 0,
error: 'Errore durante la generazione del PDF dal catalogo ID:' + error?.message,
};
}
return { fileout: '', filesize: 0, error: '' };
}
async compressPdf(inputPath, outputPath, compressione = 'printer') {
return new Promise((resolve, reject) => {
// Risolvi i percorsi assoluti
const inputFile = path.resolve(inputPath);
const outputFile = path.resolve(outputPath);
const validQualities = ['screen', 'ebook', 'printer', 'prepress', 'default'];
if (!validQualities.includes(compressione)) compressione = 'screen';
// Comando Ghostscript per compressione - impostazione per web (/screen)
const gsCommand = `gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/${compressione} -dNOPAUSE -dBATCH -dQUIET -sOutputFile="${outputFile}" "${inputFile}"`;
console.log('Eseguo comando:', gsCommand);
exec(gsCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Errore compressione PDF: ${error.message}`);
return reject(error);
}
if (stderr) {
console.error(`Ghostscript stderr: ${stderr}`);
}
console.log(`Compressione completata. File salvato in: ${outputFile}`);
resolve(outputFile);
});
});
}
static async onlinePdf(options) {
const idapp = options.idapp;
const id_catalog = options.id_catalog;
const id_raccolta = options.id_raccolta;
const stampa = options.stampa;
const compresso = options.compresso;
let mydir = '';
let risout = {};
try {
let myrec = null;
// Aggiorna il PDF OnLine, copiando il file da Generato a OnLine
if (id_catalog) {
myrec = await Catalog.findOne({ _id: id_catalog });
} else if (id_raccolta) {
myrec = await RaccoltaCataloghi.findOne({ _id: id_raccolta });
}
if (myrec) {
mydir = tools.getdirByIdApp(idapp) + '/';
// const baseurl = this.getHostByIdApp(idapp);
if (stampa) {
myrec.pdf_online_stampa = myrec.pdf_generato_stampa?.replace('_generato', '');
} else {
myrec.pdf_online = myrec.pdf_generato?.replace('_generato', '');
}
const myfile = stampa ? myrec.pdf_generato_stampa : myrec.pdf_generato;
if (myfile && (await tools.isFileExistsAsync(mydir + myfile))) {
// Aggiorna il PDF OnLine, copiando il file da Generato a OnLine
let fileOrigin = mydir + (stampa ? myrec.pdf_generato_stampa : myrec.pdf_generato);
if (compresso) {
let fileInCompressed = tools.removeFileExtension(fileOrigin) + `_compressed.pdf`;
// Se esiste allora prende questo COmpresso !
if (await tools.isFileExistsAsync(fileInCompressed)) {
fileOrigin = fileInCompressed;
} else {
}
}
const fileDest = mydir + (stampa ? myrec.pdf_online_stampa : myrec.pdf_online);
const fileDestNoDir = stampa ? myrec.pdf_online_stampa : myrec.pdf_online;
console.log(' Metti online il file ' + fileOrigin);
// copia il file
await fs.copyFile(fileOrigin, fileDest);
if (stampa) {
myrec.pdf_online_stampa_size = await tools.getSizeFile(fileDest);
} else {
myrec.pdf_online_size = await tools.getSizeFile(fileDest);
}
if (stampa) {
myrec.data_online_stampa = myrec.data_generato_stampa;
} else {
myrec.data_online = myrec.data_generato;
}
// Aggiorna il record
await myrec.save();
}
risout = { record: myrec._doc };
}
return risout;
} catch (e) {
console.error('Err Online-pdf', e.message);
return null;
}
}
}
module.exports = GenPdf;

View File

@@ -0,0 +1,179 @@
const fs = require('fs'); // 👈 Usa il modulo promises
const axios = require('axios');
const path = require('path');
/**
* Scarica un'immagine da una URL e la salva in una directory locale
* @param {string} url - L'URL dell'immagine da scaricare
* @param {string} filepath - Il percorso dove salvare l'immagine scaricata
*/
class ImageDownloader {
/**
* Scarica un'immagine da una URL e la salva in una directory locale.
* Tenta di scaricare fino a 3 volte in caso di errore, con un ritardo tra i tentativi.
*
* @param {string} url - L'URL dell'immagine da scaricare
* @param {string} filepath - Il percorso dove salvare l'immagine scaricata
* @param {number} maxRetries - Numero massimo di tentativi in caso di fallimento (default: 3)
* @param {number} delay - Ritardo in millisecondi tra i tentativi (default: 1000)
* @returns {Promise<boolean>}
*/
async downloadImage(url, filepath, options = {}) {
const {
maxRetries = 3, // Aumentato il numero di tentativi predefiniti
initialDelay = 1000, // Ritardo iniziale
maxDelay = 10000, // Ritardo massimo
timeout = 30000, // Timeout della richiesta
validateContentType = true, // Verifica del tipo di contenuto
nomefileoriginale = true,
} = options;
// Funzione per il backoff esponenziale
const getDelay = (attempt) => {
return Math.min(initialDelay * Math.pow(2, attempt - 1), maxDelay);
};
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
// Verifica se il filepath esiste già
if (await this.isFileExistsAsync(filepath)) {
fs.unlinkSync(filepath);
}
if (attempt > 1) console.log(`📥 Tentativo ${attempt}/${maxRetries} - Scaricamento: ${url}`);
const response = await axios({
url,
method: 'GET',
responseType: 'stream',
timeout: timeout,
maxRedirects: 5,
headers: {
'User-Agent':
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36',
Accept: 'image/jpeg,image/png,image/webp,image/gif,image/*', // Specifico per immagini
'Cache-Control': 'no-cache', // Evita problemi di caching
Connection: 'keep-alive',
},
validateStatus: (status) => status === 200, // Per immagini ci aspettiamo 200
maxContentLength: 10 * 1024 * 1024, // Limite di 10MB per immagine
});
// Verifica del content-type se richiesto
if (validateContentType) {
const contentType = response.headers['content-type'];
if (!contentType || !contentType.startsWith('image/')) {
throw new Error(`Content-Type non valido: ${contentType}`);
}
}
// Verifica della dimensione del file
const contentLength = parseInt(response.headers['content-length']);
if (contentLength && contentLength > 100 * 1024 * 1024) {
// 100MB limit
throw new Error('File troppo grande');
}
let downloadedBytes = 0;
response.data.on('data', (chunk) => {
downloadedBytes += chunk.length;
});
let writer = null;
if (nomefileoriginale) {
// Estrai il nome del file dall'URL o da Content-Disposition
//let fileName = this.extractFileNameFromUrl(url) || this.extractFileNameFromHeaders(response.headers);
let fileName = path.basename(response.data.responseUrl);
// Se il nome del file non è specificato, genera un nome predefinito
if (!fileName) {
fileName = `image_${Date.now()}.jpg`;
}
// Genera il percorso completo del file
const fullPath = path.join(path.dirname(filepath), fileName);
filepath = fullPath;
}
// Scrivi il file sul disco
writer = fs.createWriteStream(filepath);
response.data.pipe(writer);
await new Promise((resolve, reject) => {
writer.on('finish', resolve);
writer.on('error', (error) => {
fs.unlink(filepath, () => {}); // Pulizia in caso di errore
reject(error);
});
response.data.on('error', (error) => {
fs.unlink(filepath, () => {});
reject(error);
});
});
console.info(`✅ Immagine scaricata con successo in ${filepath}`);
return { ris: true, filepath };
} catch (error) {
console.error(`❌ Errore nel tentativo ${attempt}/${maxRetries}:`, error.message);
// Pulizia del file in caso di errore
if (await this.isFileExistsAsync(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) {
console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`);
return { ris: false };
}
const delay = getDelay(attempt);
console.info(`🔄 Attendo ${delay}ms prima del prossimo tentativo...`);
await new Promise((resolve) => setTimeout(resolve, delay));
}
}
}
// Funzione per estrarre il nome del file dall'URL
extractFileNameFromUrl(url) {
const match = url.match(/\/([^/?#]+)(?:[?#]|$)/);
return match ? decodeURIComponent(match[1]) : null;
}
// Funzione per estrarre il nome del file da Content-Disposition
extractFileNameFromHeaders(headers) {
const contentDisposition = headers['content-disposition'];
if (contentDisposition) {
const match = contentDisposition.match(/filename="([^"]+)"/);
if (match) {
return decodeURIComponent(match[1]);
}
}
return null;
}
async isFileExistsAsync (filename) {
try {
let fileExists = await fs.promises
.stat(filename)
.then(() => true)
.catch(() => false);
// console.log(filename, 'esiste', fileExists)
return fileExists;
} catch (e) {
// console.log(filename, 'esiste', 'FALSE')
return false;
}
}
}
module.exports = ImageDownloader;

View File

@@ -11,10 +11,13 @@ const Gasordine = require('../models/gasordine');
const tools = require('../tools/general'); // Assicurati di avere il file delle utility
const shared_consts = require('../tools/shared_nodejs'); // Assicurati di avere le costanti condivise
const Storehouse = require('../models/storehouse');
const ImportaDescr = require('../models/importadescr');
const { getTableContent } = require('../controllers/articleController');
const T_WEB_ArticoliFatturati = require('../models/t_web_articolifatturati');
const T_WEB_Ordini = require('../models/t_web_ordini');
const T_Web_Argomenti = require('../models/t_web_argomenti');
const { JobsInProgress } = require('../models/JobsInProgress');
class Macro {
@@ -26,10 +29,9 @@ class Macro {
}
async updateLocalDbFromGM_T_Web_Articoli(params) {
console.log('INIZIO updateLocalDbFromGM_T_Web_Articoli...', params);
let mylog = ''
let mylog = '';
let numrec = 0;
const options = {
idapp: params.idapp,
@@ -42,7 +44,7 @@ class Macro {
cmd: shared_consts.CmdQueryMs.GET,
inputdaGM: true,
...params,
}
};
let opt = {
updated: 0,
@@ -50,23 +52,33 @@ class Macro {
errors: 0,
inputdaGM: options.inputdaGM,
idapp: options.idapp,
}
};
let myjob = null;
const lavoromassivo = options.caricatutti;
if (lavoromassivo) {
myjob = await JobsInProgress.addNewJob({ idapp: options.idapp, descr: 'Riaggiorna Articoli', nomeFunzioneDbOp: 'updateAllBook', status: shared_consts.STATUS_JOB.START });
myjob = await JobsInProgress.addNewJob({
idapp: options.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 };
return {
updated: opt.updated,
imported: opt.imported,
errors: opt.errors,
mylog,
idRecUpdated: opt.idRecUpdated,
table: opt.table,
};
}
}
try {
let miomatch = {};
let miomatch2 = {};
let miolimit = 0;
@@ -85,12 +97,11 @@ class Macro {
{ DescrizioneStatoProdotto: 'Prossima uscita' },
{ DescrizioneStatoProdotto: 'In prevendita' },
{ DescrizioneStatoProdotto: 'Vendita sito' },
{ DescrizioneStatoProdotto: '2023 in commercio' }
{ DescrizioneStatoProdotto: '2023 in commercio' },
],
Ean13: { $not: /^USATO/ }
Ean13: { $not: /^USATO/ },
};
/*
1 In commercio
3 Ristampa
@@ -124,6 +135,8 @@ class Macro {
DescrizioneTipologia = 'Carte')
AND
(Ean13 NOT LIKE 'USATO%')
ORDER BY T.IdArticolo DESC, Id DESC
`;
}
} else {
@@ -141,7 +154,7 @@ class Macro {
filtroTipologia = {
$match: {
DescrizioneTipologia: { $in: ['Libri', 'Cartolibro', 'Carte'] },
}
},
};
}
@@ -151,7 +164,7 @@ class Macro {
{
$match: {
...miomatch,
}
},
},
{
$sort: {
@@ -160,12 +173,12 @@ class Macro {
},
{
$group: {
_id: "$IdArticolo",
lastRecord: { $first: "$$ROOT" }
}
_id: '$IdArticolo',
lastRecord: { $first: '$$ROOT' },
},
},
{
$replaceRoot: { newRoot: "$lastRecord" }
$replaceRoot: { newRoot: '$lastRecord' },
},
{
$lookup: {
@@ -178,20 +191,20 @@ class Macro {
$sort: { DataOra: -1 },
},
{
$limit: 1
}
]
}
$limit: 1,
},
],
},
},
{
$addFields: {
DescrizioneStatoProdotto: { $arrayElemAt: ['$StatoProdotto.Descrizione', 0] },
}
},
},
{
$match: {
...miomatch2
}
...miomatch2,
},
},
{
$lookup: {
@@ -204,22 +217,22 @@ class Macro {
$sort: { DataOra: -1 },
},
{
$limit: 1
}
]
}
$limit: 1,
},
],
},
},
{
$addFields: {
DescrizioneTipologia: { $arrayElemAt: ['$DescrizioneTipologia.Descrizione', 0] },
}
},
},
{
$match: {
$expr: {
$in: ["$DescrizioneTipologia", ["Libri", "Cartolibro"]]
}
}
$in: ['$DescrizioneTipologia', ['Libri', 'Cartolibro']],
},
},
},
{
$lookup: {
@@ -227,12 +240,12 @@ class Macro {
localField: 'IdTipoFormato',
foreignField: 'IdTipoFormato',
as: 'DescrizioneFormato',
}
},
},
{
$addFields: {
DescrizioneFormato: { $arrayElemAt: ['$DescrizioneFormato.Descrizione', 0] },
}
},
},
...(filtroTipologia ? [filtroTipologia] : []),
{
@@ -241,12 +254,12 @@ class Macro {
localField: 'IdCollana',
foreignField: 'IdCollana',
as: 'DescrizioneCollana',
}
},
},
{
$addFields: {
DescrizioneCollana: { $arrayElemAt: ['$DescrizioneCollana.Descrizione', 0] },
}
},
},
{
$lookup: {
@@ -254,12 +267,12 @@ class Macro {
localField: 'IdEdizione',
foreignField: 'CodEdizione',
as: 'editore',
}
},
},
{
$addFields: {
editore: { $arrayElemAt: ['$editore.Descrizione', 0] },
}
},
},
{
$addFields: {
@@ -270,22 +283,22 @@ class Macro {
in: {
$convert: {
input: { $trim: { input: '$$id' } },
to: "int",
to: 'int',
onError: null,
onNull: null
}
}
}
}
}
onNull: null,
},
},
},
},
},
},
{
$lookup: {
from: 't_web_autoris', // assicurati che il nome della collezione sia corretto
localField: 'ListaAutoriArray',
foreignField: 'IdAutore',
as: 'AutoriDettagliati'
}
as: 'AutoriDettagliati',
},
},
{
$addFields: {
@@ -297,18 +310,18 @@ class Macro {
$cond: [
{ $eq: ['$$value', ''] },
{ $concat: ['$$this.Nome', ' ', '$$this.Cognome'] },
{ $concat: ['$$value', ', ', '$$this.Nome', ' ', '$$this.Cognome'] }
]
}
}
}
}
{ $concat: ['$$value', ', ', '$$this.Nome', ' ', '$$this.Cognome'] },
],
},
},
},
},
},
{
$project: {
ListaAutoriArray: 0,
AutoriDettagliati: 0,
}
},
},
{
$addFields: {
@@ -316,10 +329,10 @@ class Macro {
$map: {
input: { $split: ['$ListaArgomenti', ','] },
as: 'id',
in: { $toInt: { $trim: { input: '$$id' } } }
}
}
}
in: { $toInt: { $trim: { input: '$$id' } } },
},
},
},
},
// Step: Lookup verso collezione degli argomenti, ordinando per DataOra
{
@@ -330,18 +343,16 @@ class Macro {
{
$match: {
$expr: {
$in: ['$IdArgomento',
{ $ifNull: ["$$argomentiArray", []] }
]
}
}
$in: ['$IdArgomento', { $ifNull: ['$$argomentiArray', []] }],
},
},
},
{ $sort: { DataOra: -1 } },
{ $limit: 1 },
{ $project: { Descrizione: 1 } }
{ $project: { Descrizione: 1 } },
],
as: 'ArgomentiDettagliati'
}
as: 'ArgomentiDettagliati',
},
},
// Step: Genera campo DescrArgomento concatenando tutte le descrizioni
{
@@ -354,18 +365,18 @@ class Macro {
$cond: [
{ $eq: ['$$value', ''] },
'$$this.Descrizione',
{ $concat: ['$$value', ', ', '$$this.Descrizione'] }
]
}
}
}
}
{ $concat: ['$$value', ', ', '$$this.Descrizione'] },
],
},
},
},
},
},
{
$project: {
ArgomentiDettagliati: 0,
ListaArgomentiArray: 0,
}
},
},
{
$lookup: {
@@ -375,21 +386,21 @@ class Macro {
{ $match: { $expr: { $eq: ['$Codice', '$$codice'] } } },
{ $sort: { DataOra: -1 } },
{ $limit: 1 },
{ $project: { QtaDisponibile: 1 } }
{ $project: { QtaDisponibile: 1 } },
],
as: 'DisponibileDettaglio'
}
as: 'DisponibileDettaglio',
},
},
{
$addFields: {
QtaDisponibile: { $arrayElemAt: ['$DisponibileDettaglio.QtaDisponibile', 0] }
}
QtaDisponibile: { $arrayElemAt: ['$DisponibileDettaglio.QtaDisponibile', 0] },
},
},
// Step: Pulisci i campi temporanei
{
$project: {
DisponibileDettaglio: 0,
}
},
},
{
$lookup: {
@@ -397,27 +408,25 @@ class Macro {
localField: 'IdMarchioEditoriale',
foreignField: 'IdMarchioEditoriale',
as: 'CasaEditrice',
}
},
},
{
$addFields: {
CasaEditrice: { $arrayElemAt: ['$CasaEditrice.Descrizione', 0] },
}
},
},
];
} else {
if (!options.caricatutti) {
if (options.sku) {
options.where = 'T.IdArticolo =' + options.sku + ' AND T.Ean13 = \'' + options.isbn + '\'';
options.where = 'T.IdArticolo =' + options.sku + " AND T.Ean13 = '" + options.isbn + "'";
} else {
options.where = 'T.Ean13 = \'' + options.isbn + '\'';
options.where = "T.Ean13 = '" + options.isbn + "'";
}
}
}
const recproducts = await getTableContent(options);
let recproducts = await getTableContent(options);
let idRecUpdated = null;
@@ -432,17 +441,41 @@ class Macro {
let rimuoviTabellePerIniziare = false;
let count = 0;
if (Array.isArray(recproducts)) {
if (recproducts.length > 10 && lavoromassivo && options.rimuovieventualiCancellati) {
// rimuovi dalla tabella productInfo tutti i campi date_updated_fromGM
const result = await ProductInfo.updateMany({ idapp: options.idapp }, { $unset: { date_updated_fromGM: null } });
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;
}
if (false) {
const gruppiPerIsbn = recproducts.reduce((map, product) => {
const isbn = product.Ean13;
if (!map.has(isbn)) {
map.set(isbn, [product]);
} else {
map.get(isbn).push(product);
}
return map;
}, new Map());
const isbnConMultipliRecord = Array.from(gruppiPerIsbn.entries())
.filter(([isbn, products]) => products.length > 1)
.map(([isbn]) => isbn);
recproducts = recproducts.filter((product) => isbnConMultipliRecord.includes(product.Ean13));
console.log(
`Trovati ${isbnConMultipliRecord.length} record con ISBN duplicati: ${isbnConMultipliRecord.join(', ')}`
);
}
for (const recproduct of recproducts) {
await this.elaboraProdotto(recproduct, opt);
@@ -456,7 +489,9 @@ class Macro {
if (count % 50 === 0) {
const percentuale = Math.round((count / numrec) * 100);
console.log(` *** RECORD ${count} - IMPORTATI: ${opt.imported} AGGIORNATI = ${opt.updated} (su ${numrec} RECORD) - Completato al ${percentuale}%`);
console.log(
` *** RECORD ${count} - IMPORTATI: ${opt.imported} AGGIORNATI = ${opt.updated} (su ${numrec} RECORD) - Completato al ${percentuale}%`
);
}
//}
}
@@ -464,8 +499,7 @@ class Macro {
if (rimuoviTabellePerIniziare && options.rimuovieventualiCancellati) {
await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(options.idapp);
}
if (myjob)
await myjob.terminateJob();
if (myjob) await myjob.terminateJob();
}
if (numrec > 1) {
@@ -477,17 +511,22 @@ class Macro {
}
console.log(mylog);
return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, idRecUpdated: opt.idRecUpdated, table: opt.table };
return {
updated: opt.updated,
imported: opt.imported,
errors: opt.errors,
mylog,
idRecUpdated: opt.idRecUpdated,
table: opt.table,
};
} 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;
if (myjob)
await myjob.terminateJob(true);
if (myjob) await myjob.terminateJob(true);
console.error(e.message);
return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, logerror: opt.logerror };
}
}
/**
@@ -513,8 +552,10 @@ class Macro {
indice++;
}
const percentuale = (indice / dataObjects.length * 100).toFixed(2);
console.log(`*** RECORD: ${indice} - IMPORTATI: ${imported}, AGGIORNATI = ${updated} (su ${dataObjects.length} RECORD) - Completamento: ${percentuale}%`);
const percentuale = ((indice / dataObjects.length) * 100).toFixed(2);
console.log(
`*** RECORD: ${indice} - IMPORTATI: ${imported}, AGGIORNATI = ${updated} (su ${dataObjects.length} RECORD) - Completamento: ${percentuale}%`
);
return { updated, imported, errors };
} catch (e) {
console.error(e.message);
@@ -552,7 +593,7 @@ class Macro {
{ new: true, upsert: true, strict: false }
);
} catch (e) {
console.error('Errore durante l\'inserimento:', e);
console.error("Errore durante l'inserimento:", e);
}
}
}
@@ -574,8 +615,7 @@ class Macro {
*/
aggiornaCampiDaIsbn(recmacro, recrankingisbn) {
if (!recmacro.isbn) recmacro.isbn = recrankingisbn.isbn;
if ((!recmacro.Pagine || recmacro.Pagine === 0) && recrankingisbn.Pagine)
recmacro.Pagine = recrankingisbn.Pagine;
if ((!recmacro.Pagine || recmacro.Pagine === 0) && recrankingisbn.Pagine) recmacro.Pagine = recrankingisbn.Pagine;
if (!recmacro.misure && recrankingisbn.misure) recmacro.misure = recrankingisbn.misure;
}
@@ -587,11 +627,9 @@ class Macro {
setta = false,
importa = true;
let product = { ...productInput };
let product = { ...productInput, deleted: false };
if (options.inputdaGM)
product = this.convertiDaCampiGMACampoFDV_ProductInfo(options.idapp, product);
if (options.inputdaGM) product = await this.convertiDaCampiGMACampoFDV_ProductInfo(options.idapp, product);
if (!product.title || !product.sku) importa = false;
@@ -614,7 +652,6 @@ class Macro {
await this.gestisciEditore(productInfo, product);
await this.gestisciCollana(productInfo, product);
const risrecInfo = await ProductInfo.findOneAndUpdate(
{ code: productInfo.code },
{ $set: productInfo },
@@ -625,9 +662,11 @@ class Macro {
product.idProductInfo = risrecInfo._id;
this.queryprod = { idProductInfo: product.idProductInfo };
await this.aggiornaImmagineSeNecessario(risrecInfo);
const aggiornatoimg = await this.aggiornaImmagineSeNecessario(risrecInfo);
if (!aggiornatoimg?.delete) {
await this.gestisciGasOrdine(product, risrecInfo);
await this.gestisciVariazioni(product, risrecInfo, options);
}
} else {
console.error('Errore ProductInfo:', product.code);
options.errors++;
@@ -661,7 +700,6 @@ class Macro {
await Product.findOneAndUpdate({ _id: product._id }, { $set: { idGasordine: product.idGasordine } });
}
}
preparaProductInfo(product) {
@@ -709,7 +747,7 @@ class Macro {
}
}
convertiDaCampiGMACampoFDV_ProductInfo(idapp, productGM) {
async convertiDaCampiGMACampoFDV_ProductInfo(idapp, productGM) {
let productFDV = {};
/* productGM CAMPI
@@ -758,13 +796,31 @@ class Macro {
}
*/
const magazzino_macro = 'Gruppo Macro';
let recstorehouse = await Storehouse.findOne({ idapp, name: magazzino_macro }).lean();
if (!recstorehouse) {
// Non esiste questo produttore, quindi lo creo !
recstorehouse = new Storehouse({ idapp, name: magazzino_macro });
ris = await recstorehouse.save();
recstorehouse = await Storehouse.findOne({ idapp, name: prod.magazzino_name }).lean();
}
// Controlla se il Titolo esiste nella tabella temporanea
let titolo = productGM.Titolo;
const tabdescr = await ImportaDescr.findOne({ code: productGM.Ean13 }).lean();
if (tabdescr?.title) {
titolo = tabdescr.title
}
const recproduct = {
idapp: idapp,
isbn: productGM.Ean13,
// id_wp: '',
sku: productGM.IdArticolo,
title: productGM.Titolo, // productInfo.name.replace(/ - Usato$| - Nuovo$| - Epub$| - Ebook$| - Mobi$| - DVD$| - Streaming$| - Download$/, "");
title: titolo, // productInfo.name.replace(/ - Usato$| - Nuovo$| - Epub$| - Ebook$| - Mobi$| - DVD$| - Streaming$| - Download$/, "");
description: '',
short_descr: '',
collezione: productGM.DescrizioneCollana,
@@ -786,54 +842,57 @@ class Macro {
ristampa: productGM.Ristampa,
eta: productGM.FasciaEta,
// addtocart_link: '',
Quantita: productGM.QtaDisponibile || undefined,
stockQty: productGM.QtaDisponibile || undefined,
date_pub: productGM.DataPubblicazione ? tools.getDateFromISOString(productGM.DataPubblicazione) : null,
sottotitolo: productGM.Sottotitolo,
productTypes: [shared_consts.PRODUCTTYPE.PRODUCT],
date_updated_fromGM: new Date(),
}
idStorehouses: [recstorehouse._id],
};
let vers = 0;
if (productGM.DescrizioneTipologia === 'Usato')
vers = shared_consts.PRODUCTTYPE.USATO;
if (productGM.DescrizioneTipologia === 'Download')
vers = shared_consts.PRODUCTTYPE.DOWNLOAD;
else if (productGM.DescrizioneTipologia === 'DVD')
vers = shared_consts.PRODUCTTYPE.DVD;
else if (productGM.DescrizioneTipologia === 'Epub')
vers = shared_consts.PRODUCTTYPE.EPUB;
else if (productGM.DescrizioneTipologia === 'Mobi')
vers = shared_consts.PRODUCTTYPE.MOBI;
else if (productGM.DescrizioneTipologia === 'PDF')
vers = shared_consts.PRODUCTTYPE.PDF;
else if (productGM.DescrizioneTipologia === 'Streaming')
vers = shared_consts.PRODUCTTYPE.STREAMING;
else
vers = shared_consts.PRODUCTTYPE.NUOVO;
if (productGM.DescrizioneTipologia === 'Usato') vers = shared_consts.PRODUCTTYPE.USATO;
if (productGM.DescrizioneTipologia === 'Download') vers = shared_consts.PRODUCTTYPE.DOWNLOAD;
else if (productGM.DescrizioneTipologia === 'DVD') vers = shared_consts.PRODUCTTYPE.DVD;
else if (productGM.DescrizioneTipologia === 'Epub') vers = shared_consts.PRODUCTTYPE.EPUB;
else if (productGM.DescrizioneTipologia === 'Mobi') vers = shared_consts.PRODUCTTYPE.MOBI;
else if (productGM.DescrizioneTipologia === 'PDF') vers = shared_consts.PRODUCTTYPE.PDF;
else if (productGM.DescrizioneTipologia === 'Streaming') vers = shared_consts.PRODUCTTYPE.STREAMING;
else vers = shared_consts.PRODUCTTYPE.NUOVO;
recproduct.Versione = vers;
return recproduct
return recproduct;
}
/**
* Gestisce le categorie e sottocategorie del prodotto.
*/
async gestisciCategorie(productInfo, product) {
try {
if (product.DescrArgomento) {
productInfo.idCatProds = [];
const reccateg = await CatProd.findOne({ idapp: this.idapp, name: product.DescrArgomento }).lean();
const reccateg = await CatProd.findOne({ idapp: this.idapp, name: product.DescrArgomento });
let nuovaCategoria = null;
if (!reccateg) {
nuovaCategoria = new CatProd({ idapp: this.idapp, name: product.DescrArgomento });
await nuovaCategoria.save();
}
const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null)
if (myriscat)
productInfo.idCatProds.push(myriscat);
if (!reccateg?.idArgomento && product.DescrArgomento) {
// Se non c'è l'argomento, allora lo cerco nel DB
const recarg = await T_Web_Argomenti.findOne({ Descrizione: product.DescrArgomento }).lean();
if (recarg) {
reccateg.idArgomento = recarg.IdArgomento;
await reccateg.save();
}
}
const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null);
if (myriscat) productInfo.idCatProds.push(myriscat);
} else {
if (product.categories) {
// const arrcat = product.categories.trim().split(',');
@@ -850,12 +909,14 @@ class Macro {
await nuovaCategoria.save();
}
const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null)
if (myriscat)
productInfo.idCatProds.push(myriscat);
const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null);
if (myriscat) productInfo.idCatProds.push(myriscat);
}
}
}
} catch (error) {
console.error('Errore gestisciCategorie:', error);
}
}
/**
@@ -863,16 +924,18 @@ class Macro {
*/
async gestisciAutori(productInfo, product) {
if (product.Autore) {
let arrAuthor = []
if (product.id_wp)
arrAuthor = this.estraiAutori_FDV(product.Autore);
else
arrAuthor = this.estraiAutori(product.Autore);
let arrAuthor = [];
if (product.id_wp) arrAuthor = this.estraiAutori_FDV(product.Autore);
else arrAuthor = this.estraiAutori(product.Autore);
productInfo.idAuthors = [];
for (const author of arrAuthor) {
const recauthor = await Author.findOne({ idapp: this.idapp, name: author.name, surname: author.surname }).lean();
const recauthor = await Author.findOne({
idapp: this.idapp,
name: author.name,
surname: author.surname,
}).lean();
let nuovoAutore = null;
if (!recauthor) {
@@ -881,8 +944,7 @@ class Macro {
}
const myrisautore = recauthor?._id || (nuovoAutore ? nuovoAutore._id : '');
if (myrisautore)
productInfo.idAuthors.push(myrisautore);
if (myrisautore) productInfo.idAuthors.push(myrisautore);
}
}
}
@@ -899,9 +961,8 @@ class Macro {
if (arrrecns && arrrecns.length === 4) {
name = arrrecns[0].trim() + ' ' + arrrecns[1].trim();
surname = arrrecns[2].trim() + ' ' + arrrecns[3].trim();;
surname = arrrecns[2].trim() + ' ' + arrrecns[3].trim();
} else {
if (arrrecns && arrrecns.length === 1) {
name = arrrecns[0].trim();
} else {
@@ -948,8 +1009,7 @@ class Macro {
return;
}
}
if (recpublisher?._id || nuovoEditore?._id)
productInfo.idPublisher = recpublisher?._id || nuovoEditore._id;
if (recpublisher?._id || nuovoEditore?._id) productInfo.idPublisher = recpublisher?._id || nuovoEditore._id;
}
}
@@ -970,12 +1030,10 @@ class Macro {
return;
}
}
if (reccollana?._id || nuovaCollana?._id)
productInfo.idCollana = reccollana?._id || nuovaCollana._id;
if (reccollana?._id || nuovaCollana?._id) productInfo.idCollana = reccollana?._id || nuovaCollana._id;
}
}
/**
* Aggiorna l'immagine se necessario.
*/
@@ -984,6 +1042,8 @@ class Macro {
if (aggiornatoimg) {
await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: prodInfo });
}
return aggiornatoimg;
}
/**
@@ -1006,7 +1066,7 @@ class Macro {
ristampa: product.ristampa || '',
eta: product.eta || '',
addtocart_link: product.addtocart_link || '',
quantita: product.Quantita ? parseInt(product.Quantita) : 0,
quantita: product.stockQty ? parseInt(product.stockQty) : 0,
preOrderDate: product.preOrderDate || null,
};
}
@@ -1033,7 +1093,9 @@ class Macro {
const myproduct = {
...product,
...(!product.isbn ? [{ isbn: risrecInfo.code }] : []),
...(!product.maxbookableGASQty && risrecInfo.maxbookableGASQty ? [{ maxbookableGASQty: risrecInfo.maxbookableGASQty }] : []),
...(!product.maxbookableGASQty && risrecInfo.maxbookableGASQty
? [{ maxbookableGASQty: risrecInfo.maxbookableGASQty }]
: []),
idapp: this.idapp,
arrvariazioni: [variazione],
};
@@ -1042,11 +1104,15 @@ class Macro {
if (recold) {
const arrvariazioni = this.aggiornaVariazioni(recold.arrvariazioni, variazione);
const updatedDoc = await Product.findOneAndUpdate(this.queryprod, { $set: { arrvariazioni } }, {
const updatedDoc = await Product.findOneAndUpdate(
this.queryprod,
{ $set: { arrvariazioni } },
{
upsert: true,
new: true, // restituisce il documento aggiornato
includeResultMetadata: true
});
includeResultMetadata: true,
}
);
if (updatedDoc && updatedDoc.lastErrorObject) {
const wasUpserted = updatedDoc.lastErrorObject.upserted !== undefined;
const wasUpdated = updatedDoc.lastErrorObject.n === 1 && !wasUpserted;
@@ -1054,9 +1120,7 @@ class Macro {
if (wasUpserted || wasUpdated) {
options.updated++;
options.table = 'products';
options.idRecUpdated = wasUpserted
? updatedDoc.lastErrorObject.upserted
: updatedDoc.value._id;
options.idRecUpdated = wasUpserted ? updatedDoc.lastErrorObject.upserted : updatedDoc.value._id;
}
}
@@ -1065,10 +1129,13 @@ class Macro {
}
}
if (!recold || this.isModified(recold, myproduct) || !this.recProductExist) {
const updatedDoc = await Product.findOneAndUpdate(this.queryprod, { $set: myproduct },
const updatedDoc = await Product.findOneAndUpdate(
this.queryprod,
{ $set: myproduct },
{
new: true, upsert: true,
includeResultMetadata: true
new: true,
upsert: true,
includeResultMetadata: true,
}
);
if (updatedDoc && updatedDoc.lastErrorObject) {
@@ -1078,9 +1145,7 @@ class Macro {
if (wasUpserted || wasUpdated) {
options.imported++;
options.table = 'products';
options.idRecUpdated = wasUpserted
? updatedDoc.lastErrorObject.upserted
: updatedDoc.value._id;
options.idRecUpdated = wasUpserted ? updatedDoc.lastErrorObject.upserted : updatedDoc.value._id;
}
}
}
@@ -1099,20 +1164,23 @@ class Macro {
const listaCampi = [
'idapp',
'isbn',
'price',
'stockQty',
//++FIELD_PRODUCT
]
];
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 }] });
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

@@ -0,0 +1,84 @@
const shared_consts = require('../tools/shared_nodejs');
const cartModel = require('../models/cart');
const { ObjectId } = require('mongodb');
const Gasordine = require('../models/gasordine');
const Order = require('../models/order');
const Scontistica = require('../models/scontistica');
class OrderClass {
constructor() {}
static initOrderTotals(order) {
order.TotalPriceProduct = 0;
order.TotalPriceProductCalc = 0;
order.modify_at = new Date();
}
static getNonCumulativeDiscounts(discounts) {
return discounts.filter((rec) => !rec.cumulativo);
}
static applyNonCumulativeDiscounts(order, discounts) {
let qtadascontare = order.quantity + order.quantitypreordered;
let qtanonscontata = 0;
let sconti_da_applicare = [];
while (qtadascontare > 0) {
let scontoapplicato = null;
// Filtriamo gli sconti non cumulativi
for (const sconto of OrderClass.getNonCumulativeDiscounts(discounts)) {
if (qtadascontare >= sconto.qta && sconto.qta > 0) {
// Se la quantità da scontare è maggiore o uguale alla quantità dello sconto, applica lo sconto completo
scontoapplicato = { ...sconto, qtadascontare: sconto.qta };
break; // Esci dal ciclo, abbiamo trovato lo sconto applicabile
} else if (qtadascontare > 0) {
// Se la quantità da scontare è inferiore allo sconto, applica solo la quantità disponibile
scontoapplicato = { ...sconto, qtadascontare: qtadascontare };
qtadascontare = 0; // Abbiamo finito le quantità da scontare
break;
}
}
// Se c'è uno sconto applicato, aggiungilo alla lista e riduci la quantità
if (scontoapplicato && scontoapplicato.qtadascontare > 0) {
sconti_da_applicare.push(scontoapplicato);
qtadascontare -= scontoapplicato.qtadascontare;
} else {
// Se non ci sono più sconti da applicare, la quantità rimasta è non scontata
qtanonscontata = qtadascontare;
qtadascontare = 0;
}
}
return { sconti_da_applicare, qtanonscontata };
}
static calculateDiscountedPrice(order, sconti_da_applicare, qtanonscontata) {
let total = 0;
for (const sconto of sconti_da_applicare) {
if (sconto.perc_sconto > 0) {
total += sconto.qtadascontare * order.price * (1 - sconto.perc_sconto / 100);
} else {
total += sconto.price;
}
}
if (qtanonscontata > 0) {
total += order.price * qtanonscontata;
}
return total;
}
static calculateFullPrice(order) {
return order.price * order.quantity + order.price * order.quantitypreordered;
}
}
module.exports = OrderClass;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,885 @@
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var axios = require('axios');
var apiUrl = 'https://api.cloudflare.com/client/v4'; // Endpoint
var MailinaboxClass = require('./Mailinabox.js');
var CloudFlare =
/*#__PURE__*/
function () {
function CloudFlare(config) {
_classCallCheck(this, CloudFlare);
this.config = config ? config : {};
if (!this.config.arrTokens) {
this.config.arrTokens = process.env.CLOUDFLARE_TOKENS;
}
}
_createClass(CloudFlare, [{
key: "init",
value: function init() {
if (this.config.arrTokens) {
// this.zones = this.fetchCloudflareZones(this.config.apiToken);
this.zones = [];
this.dnsRecords = null;
}
}
}, {
key: "fetchCloudflareZones",
value: function fetchCloudflareZones(apiToken) {
var response, _iteratorNormalCompletion, _didIteratorError, _iteratorError, _iterator, _step, zone, domain;
return regeneratorRuntime.async(function fetchCloudflareZones$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
_context.prev = 0;
_context.next = 3;
return regeneratorRuntime.awrap(axios.get(apiUrl + '/zones', {
headers: {
'Authorization': "Bearer ".concat(apiToken),
// Autenticazione con token
'Content-Type': 'application/json' // Tipo di contenuto
}
}));
case 3:
response = _context.sent;
// Estrai i dati dalla risposta
this.zones = response.data.result;
if (!(this.zones && this.zones.length > 0)) {
_context.next = 33;
break;
}
_iteratorNormalCompletion = true;
_didIteratorError = false;
_iteratorError = undefined;
_context.prev = 9;
_iterator = this.zones[Symbol.iterator]();
case 11:
if (_iteratorNormalCompletion = (_step = _iterator.next()).done) {
_context.next = 19;
break;
}
zone = _step.value;
domain = zone.name;
_context.next = 16;
return regeneratorRuntime.awrap(this.findAndUpdateOnSite(domain, zone, apiToken));
case 16:
_iteratorNormalCompletion = true;
_context.next = 11;
break;
case 19:
_context.next = 25;
break;
case 21:
_context.prev = 21;
_context.t0 = _context["catch"](9);
_didIteratorError = true;
_iteratorError = _context.t0;
case 25:
_context.prev = 25;
_context.prev = 26;
if (!_iteratorNormalCompletion && _iterator["return"] != null) {
_iterator["return"]();
}
case 28:
_context.prev = 28;
if (!_didIteratorError) {
_context.next = 31;
break;
}
throw _iteratorError;
case 31:
return _context.finish(28);
case 32:
return _context.finish(25);
case 33:
return _context.abrupt("return", this.zones);
case 36:
_context.prev = 36;
_context.t1 = _context["catch"](0);
console.error('Errore durante il recupero delle zone di Cloudflare:', _context.t1.message);
case 39:
case "end":
return _context.stop();
}
}
}, null, this, [[0, 36], [9, 21, 25, 33], [26,, 28, 32]]);
}
}, {
key: "findAndUpdateOnSite",
value: function findAndUpdateOnSite(domain, zone, apiToken) {
var Site, normalizedDomain, recsite, modif, miab, dkim;
return regeneratorRuntime.async(function findAndUpdateOnSite$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
_context2.prev = 0;
Site = require('../models/site');
domain = domain.replace(/^https?:\/\//, '');
normalizedDomain = domain.startsWith("http://") || domain.startsWith("https://") ? domain : "https://" + domain; // Trova il sito usando il dominio normalizzato
_context2.next = 6;
return regeneratorRuntime.awrap(Site.findOne({
host: normalizedDomain
}));
case 6:
recsite = _context2.sent;
if (!recsite) {
_context2.next = 21;
break;
}
// Aggiorna i parametri token e zoneId
modif = recsite.cf_token !== apiToken || recsite.cf_zoneId !== zone.id;
if (!(modif && apiToken)) {
_context2.next = 12;
break;
}
_context2.next = 12;
return regeneratorRuntime.awrap(Site.findOneAndUpdate({
_id: recsite._id
}, {
$set: {
cf_token: apiToken,
cf_zoneId: zone.id
}
}, {
"new": true
}).then(function (updatedSite) {
console.log('Site aggiornato:', updatedSite);
})["catch"](function (error) {
console.error('Errore durante l\'aggiornamento del Site:', error);
}));
case 12:
if (!(recsite.enable_servermail && !recsite.dkim)) {
_context2.next = 21;
break;
}
miab = new MailinaboxClass(null);
miab.init();
_context2.next = 17;
return regeneratorRuntime.awrap(miab.getDKIMRecord(recsite.host.replace(/^https?:\/\//, '')));
case 17:
dkim = _context2.sent;
if (!dkim) {
_context2.next = 21;
break;
}
_context2.next = 21;
return regeneratorRuntime.awrap(Site.findOneAndUpdate({
_id: recsite._id
}, {
$set: {
dkim: dkim
}
}));
case 21:
_context2.next = 26;
break;
case 23:
_context2.prev = 23;
_context2.t0 = _context2["catch"](0);
console.error('Errore durante il recupero dei record DNS di Cloudflare:', _context2.t0.message);
case 26:
case "end":
return _context2.stop();
}
}
}, null, null, [[0, 23]]);
} // Funzione per estrarre i record DNS
}, {
key: "fetchDNSRecords",
value: function fetchDNSRecords(apiToken, zoneId) {
var apiUrlDNS, response;
return regeneratorRuntime.async(function fetchDNSRecords$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
apiUrlDNS = apiUrl + "/zones/".concat(zoneId, "/dns_records");
_context3.prev = 1;
_context3.next = 4;
return regeneratorRuntime.awrap(axios.get(apiUrlDNS, {
headers: {
'Authorization': "Bearer ".concat(apiToken),
// Autenticazione con token
'Content-Type': 'application/json' // Tipo di contenuto
}
}));
case 4:
response = _context3.sent;
this.dnsRecords = response.data.result;
return _context3.abrupt("return", this.dnsRecords);
case 9:
_context3.prev = 9;
_context3.t0 = _context3["catch"](1);
console.error('Errore durante il recupero dei record DNS di Cloudflare:', _context3.t0.message);
case 12:
case "end":
return _context3.stop();
}
}
}, null, this, [[1, 9]]);
} // Funzione per aggiornare un record DNS
}, {
key: "updateDNSRecord",
value: function updateDNSRecord(apiToken, zoneId, dnsRecordId, newDnsRecordData) {
var apiUrlDNS, response, updatedRecord;
return regeneratorRuntime.async(function updateDNSRecord$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
apiUrlDNS = apiUrl + "/zones/".concat(zoneId, "/dns_records/").concat(dnsRecordId);
_context4.prev = 1;
_context4.next = 4;
return regeneratorRuntime.awrap(axios.put(apiUrlDNS, newDnsRecordData, {
headers: {
'Authorization': "Bearer ".concat(apiToken),
// Autenticazione con token
'Content-Type': 'application/json' // Tipo di contenuto
}
}));
case 4:
response = _context4.sent;
updatedRecord = response.data.result; // Stampa il record DNS aggiornato
console.log('Record DNS aggiornato:', updatedRecord);
return _context4.abrupt("return", updatedRecord);
case 10:
_context4.prev = 10;
_context4.t0 = _context4["catch"](1);
console.error('Errore durante l\'aggiornamento del record DNS:', _context4.t0.message);
case 13:
case "end":
return _context4.stop();
}
}
}, null, null, [[1, 10]]);
} // Funzione per creare un record DNS di CloudFlare
}, {
key: "createDNSRecord",
value: function createDNSRecord(apiToken, zoneId, dnsRecordData) {
var apiUrlDNS, response, createdRecord;
return regeneratorRuntime.async(function createDNSRecord$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
apiUrlDNS = apiUrl + "/zones/".concat(zoneId, "/dns_records");
_context5.prev = 1;
_context5.next = 4;
return regeneratorRuntime.awrap(axios.post(apiUrlDNS, dnsRecordData, {
headers: {
'Authorization': "Bearer ".concat(apiToken),
// Autenticazione con token
'Content-Type': 'application/json' // Tipo di contenuto
}
}));
case 4:
response = _context5.sent;
createdRecord = response.data.result;
console.log('Record DNS creato:', createdRecord);
return _context5.abrupt("return", createdRecord);
case 10:
_context5.prev = 10;
_context5.t0 = _context5["catch"](1);
console.error('Errore durante la creazione del record DNS:', _context5.t0.message);
case 13:
case "end":
return _context5.stop();
}
}
}, null, null, [[1, 10]]);
} // Funzione per cancellare un record DNS di CloudFlare
}, {
key: "deleteDNSRecord",
value: function deleteDNSRecord(apiToken, zoneId, dnsRecordId) {
var apiUrlDNS, response, deletedRecord;
return regeneratorRuntime.async(function deleteDNSRecord$(_context6) {
while (1) {
switch (_context6.prev = _context6.next) {
case 0:
apiUrlDNS = apiUrl + "/zones/".concat(zoneId, "/dns_records/").concat(dnsRecordId);
_context6.prev = 1;
_context6.next = 4;
return regeneratorRuntime.awrap(axios["delete"](apiUrlDNS, {
headers: {
'Authorization': "Bearer ".concat(apiToken),
// Autenticazione con token
'Content-Type': 'application/json' // Tipo di contenuto
}
}));
case 4:
response = _context6.sent;
deletedRecord = response.data.result;
console.log('Record DNS cancellato:', deletedRecord);
return _context6.abrupt("return", deletedRecord);
case 10:
_context6.prev = 10;
_context6.t0 = _context6["catch"](1);
console.error('Errore durante la cancellazione del record DNS:', _context6.t0.message);
case 13:
case "end":
return _context6.stop();
}
}
}, null, null, [[1, 10]]);
}
}, {
key: "setCorrectIpsOnDNS",
value: function setCorrectIpsOnDNS(domainrec) {
var arrparams, i;
return regeneratorRuntime.async(function setCorrectIpsOnDNS$(_context7) {
while (1) {
switch (_context7.prev = _context7.next) {
case 0:
arrparams = [{
urladd: '',
paramsite: 'host_ip',
type: 'A'
}, {
urladd: 'test.',
paramsite: 'host_test_ip',
type: 'A'
}, {
urladd: 'api.',
paramsite: 'host_api_ip',
type: 'A'
}, {
urladd: 'testapi.',
paramsite: 'host_testapi_ip',
type: 'A'
}, {
urladd: 'www.',
paramsite: 'host',
type: 'CNAME'
}];
i = 0;
case 2:
if (!(i < arrparams.length)) {
_context7.next = 8;
break;
}
_context7.next = 5;
return regeneratorRuntime.awrap(this.setSingleIpsOnDNS(domainrec.name, arrparams[i]));
case 5:
i++;
_context7.next = 2;
break;
case 8:
_context7.next = 10;
return regeneratorRuntime.awrap(this.setServerMail(domainrec));
case 10:
_context7.next = 12;
return regeneratorRuntime.awrap(new Promise(function (resolve) {
return setTimeout(resolve, 3000);
}));
case 12:
case "end":
return _context7.stop();
}
}
}, null, this);
}
}, {
key: "setServerMail",
value: function setServerMail(domainrec) {
var _this = this;
var Site, domain, normalizedDomain;
return regeneratorRuntime.async(function setServerMail$(_context9) {
while (1) {
switch (_context9.prev = _context9.next) {
case 0:
_context9.prev = 0;
// get the parameters (Token and zoneId on Database)
Site = require('../models/site');
domain = domainrec.name.replace(/^https?:\/\//, '');
normalizedDomain = domain.startsWith("http://") || domain.startsWith("https://") ? domain : "https://" + domain; // Trova il sito usando il dominio normalizzato
_context9.next = 6;
return regeneratorRuntime.awrap(Site.findOne({
host: normalizedDomain
}).lean().then(function _callee(site) {
var myarrrecdns, recTypeMX, newRecord, recTypeTXTspf1, contentTXTspf1, _newRecord, nameDkimtoFind, recTypeTXTDKIM, contentTXTDKIM, _newRecord2, nameDmarctoFind, recTypeTXTdmarc, contentTXTdmarc, _newRecord3, myType, strfind, contentExpected, rectofind, _newRecord4, _newRecord5;
return regeneratorRuntime.async(function _callee$(_context8) {
while (1) {
switch (_context8.prev = _context8.next) {
case 0:
if (!site) {
_context8.next = 91;
break;
}
if (!(site.cf_token && site.cf_zoneId)) {
_context8.next = 91;
break;
}
_context8.next = 4;
return regeneratorRuntime.awrap(_this.fetchDNSRecords(site.cf_token, site.cf_zoneId));
case 4:
myarrrecdns = _context8.sent;
_context8.next = 7;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'MX' && rec.name === domain;
}));
case 7:
recTypeMX = _context8.sent;
if (!recTypeMX) {
_context8.next = 14;
break;
}
if (!(recTypeMX.content !== site.servermail)) {
_context8.next = 12;
break;
}
recTypeMX.content = site.servermail;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, recTypeMX.id, recTypeMX));
case 12:
_context8.next = 17;
break;
case 14:
// create a new record
newRecord = {
type: 'MX',
name: domain,
content: site.servermail,
ttl: 1,
proxied: false,
priority: 10
};
_context8.next = 17;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, newRecord));
case 17:
_context8.next = 19;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'TXT' && rec.name === domain && rec.content.indexOf('v=spf1') > -1;
}));
case 19:
recTypeTXTspf1 = _context8.sent;
if (!site.servermailip) {
_context8.next = 31;
break;
}
contentTXTspf1 = "v=spf1 a mx:".concat(site.servermail, " ip4:").concat(site.servermailip, " ~all");
if (!recTypeTXTspf1) {
_context8.next = 28;
break;
}
if (!(recTypeTXTspf1.content !== contentTXTspf1)) {
_context8.next = 26;
break;
}
recTypeTXTspf1.content = contentTXTspf1;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, recTypeTXTspf1.id, recTypeTXTspf1));
case 26:
_context8.next = 31;
break;
case 28:
// create a new record
_newRecord = {
type: 'TXT',
name: domain,
content: contentTXTspf1,
ttl: 3600
};
_context8.next = 31;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, _newRecord));
case 31:
// mail._domainkey.nomedominio v=DKIM1; h=sha256; k=rsa; s=email; p=<dkim>
nameDkimtoFind = "mail._domainkey.".concat(domain);
_context8.next = 34;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'TXT' && rec.name === nameDkimtoFind;
}));
case 34:
recTypeTXTDKIM = _context8.sent;
if (!site.dkim) {
_context8.next = 46;
break;
}
contentTXTDKIM = "v=DKIM1; h=sha256; k=rsa; s=email; p=".concat(site.dkim);
if (!recTypeTXTDKIM) {
_context8.next = 43;
break;
}
if (!(recTypeTXTDKIM.content !== contentTXTDKIM)) {
_context8.next = 41;
break;
}
recTypeTXTDKIM.content = contentTXTDKIM;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, recTypeTXTDKIM.id, recTypeTXTDKIM));
case 41:
_context8.next = 46;
break;
case 43:
// create a new record
_newRecord2 = {
type: 'TXT',
name: nameDkimtoFind,
content: contentTXTDKIM,
ttl: 1
};
_context8.next = 46;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, _newRecord2));
case 46:
// DMARC:
nameDmarctoFind = "_dmarc.".concat(domain);
_context8.next = 49;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'TXT' && rec.name === nameDmarctoFind && rec.content.indexOf('v=DMARC1') > -1;
}));
case 49:
recTypeTXTdmarc = _context8.sent;
if (!site.servermailip) {
_context8.next = 61;
break;
}
contentTXTdmarc = "v=DMARC1; p=quarantine; ruf=mailto:dmarc@".concat(domain, ";");
if (!recTypeTXTdmarc) {
_context8.next = 58;
break;
}
if (!(recTypeTXTdmarc.content !== contentTXTdmarc)) {
_context8.next = 56;
break;
}
recTypeTXTdmarc.content = contentTXTdmarc;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, recTypeTXTspf1.id, recTypeTXTspf1));
case 56:
_context8.next = 61;
break;
case 58:
// create a new record
_newRecord3 = {
type: 'TXT',
name: nameDmarctoFind,
content: contentTXTdmarc,
ttl: 1
};
_context8.next = 61;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, _newRecord3));
case 61:
// AutoConfig:
myType = 'CNAME';
strfind = "autoconfig.".concat(domain);
contentExpected = site.servermail;
_context8.next = 66;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'CNAME' && rec.name === strfind;
}));
case 66:
rectofind = _context8.sent;
if (!rectofind) {
_context8.next = 73;
break;
}
if (!(rectofind.content !== contentExpected)) {
_context8.next = 71;
break;
}
rectofind.content = contentExpected;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, rectofind.id, rectofind));
case 71:
_context8.next = 76;
break;
case 73:
// create a new record
_newRecord4 = {
type: myType,
name: strfind,
content: contentExpected,
ttl: 1
};
_context8.next = 76;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, _newRecord4));
case 76:
// AutoDiscover:
myType = 'CNAME';
strfind = "autodiscover.".concat(domain);
contentExpected = site.servermail;
_context8.next = 81;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === 'CNAME' && rec.name === strfind;
}));
case 81:
rectofind = _context8.sent;
if (!rectofind) {
_context8.next = 88;
break;
}
if (!(rectofind.content !== contentExpected)) {
_context8.next = 86;
break;
}
rectofind.content = contentExpected;
return _context8.abrupt("return", _this.updateDNSRecord(site.cf_token, site.cf_zoneId, rectofind.id, rectofind));
case 86:
_context8.next = 91;
break;
case 88:
// create a new record
_newRecord5 = {
type: myType,
name: strfind,
content: contentExpected,
ttl: 1
};
_context8.next = 91;
return regeneratorRuntime.awrap(_this.createDNSRecord(site.cf_token, site.cf_zoneId, _newRecord5));
case 91:
case "end":
return _context8.stop();
}
}
});
}));
case 6:
_context9.next = 11;
break;
case 8:
_context9.prev = 8;
_context9.t0 = _context9["catch"](0);
console.error('e', _context9.t0);
case 11:
case "end":
return _context9.stop();
}
}
}, null, null, [[0, 8]]);
}
}, {
key: "setSingleIpsOnDNS",
value: function setSingleIpsOnDNS(domain, paramobj) {
var _this2 = this;
var Site, normalizedDomain;
return regeneratorRuntime.async(function setSingleIpsOnDNS$(_context11) {
while (1) {
switch (_context11.prev = _context11.next) {
case 0:
_context11.prev = 0;
// get the parameters (Token and zoneId on Database)
Site = require('../models/site');
domain = domain.replace(/^https?:\/\//, '');
normalizedDomain = domain.startsWith("http://") || domain.startsWith("https://") ? domain : "https://" + domain; // Trova il sito usando il dominio normalizzato
_context11.next = 6;
return regeneratorRuntime.awrap(Site.findOne({
host: normalizedDomain
}).lean().then(function _callee2(site) {
var myarrrecdns, nametofind, recType, paramexpected, newRecord;
return regeneratorRuntime.async(function _callee2$(_context10) {
while (1) {
switch (_context10.prev = _context10.next) {
case 0:
if (!site) {
_context10.next = 20;
break;
}
if (!(site.cf_token && site.cf_zoneId)) {
_context10.next = 20;
break;
}
_context10.next = 4;
return regeneratorRuntime.awrap(_this2.fetchDNSRecords(site.cf_token, site.cf_zoneId));
case 4:
myarrrecdns = _context10.sent;
nametofind = paramobj.urladd + domain; // find
_context10.next = 8;
return regeneratorRuntime.awrap(myarrrecdns.find(function (rec) {
return rec.type === paramobj.type && rec.name === nametofind;
}));
case 8:
recType = _context10.sent;
paramexpected = '';
try {
paramexpected = site[paramobj.paramsite].replace(/^https?:\/\//, '');
;
} catch (e) {}
if (!(recType && paramexpected)) {
_context10.next = 17;
break;
}
if (!(recType.content !== paramexpected)) {
_context10.next = 15;
break;
}
recType.content = paramexpected;
return _context10.abrupt("return", _this2.updateDNSRecord(site.cf_token, site.cf_zoneId, recType.id, recType));
case 15:
_context10.next = 20;
break;
case 17:
// create a new record
newRecord = {
type: paramobj.type,
name: nametofind,
content: paramexpected,
ttl: 1,
proxied: true
};
_context10.next = 20;
return regeneratorRuntime.awrap(_this2.createDNSRecord(site.cf_token, site.cf_zoneId, newRecord));
case 20:
case "end":
return _context10.stop();
}
}
});
}));
case 6:
_context11.next = 11;
break;
case 8:
_context11.prev = 8;
_context11.t0 = _context11["catch"](0);
console.error('e', _context11.t0);
case 11:
case "end":
return _context11.stop();
}
}
}, null, null, [[0, 8]]);
}
}]);
return CloudFlare;
}();
module.exports = CloudFlare;

1745
src/server/modules/dist/CronMod.dev.js vendored Normal file

File diff suppressed because it is too large Load Diff

45
src/server/modules/dist/ErrorHandler.dev.js vendored Executable file
View File

@@ -0,0 +1,45 @@
"use strict";
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _wrapNativeSuper(Class) { var _cache = typeof Map === "function" ? new Map() : undefined; _wrapNativeSuper = function _wrapNativeSuper(Class) { if (Class === null || !_isNativeFunction(Class)) return Class; if (typeof Class !== "function") { throw new TypeError("Super expression must either be null or a function"); } if (typeof _cache !== "undefined") { if (_cache.has(Class)) return _cache.get(Class); _cache.set(Class, Wrapper); } function Wrapper() { return _construct(Class, arguments, _getPrototypeOf(this).constructor); } Wrapper.prototype = Object.create(Class.prototype, { constructor: { value: Wrapper, enumerable: false, writable: true, configurable: true } }); return _setPrototypeOf(Wrapper, Class); }; return _wrapNativeSuper(Class); }
function isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Date.prototype.toString.call(Reflect.construct(Date, [], function () {})); return true; } catch (e) { return false; } }
function _construct(Parent, args, Class) { if (isNativeReflectConstruct()) { _construct = Reflect.construct; } else { _construct = function _construct(Parent, args, Class) { var a = [null]; a.push.apply(a, args); var Constructor = Function.bind.apply(Parent, a); var instance = new Constructor(); if (Class) _setPrototypeOf(instance, Class.prototype); return instance; }; } return _construct.apply(null, arguments); }
function _isNativeFunction(fn) { return Function.toString.call(fn).indexOf("[native code]") !== -1; }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
var TypedError =
/*#__PURE__*/
function (_Error) {
_inherits(TypedError, _Error);
function TypedError(args, status, type, error) {
var _this;
_classCallCheck(this, TypedError);
_this = _possibleConstructorReturn(this, _getPrototypeOf(TypedError).call(this, args));
_this.status = status;
_this.type = type;
_this.error = error;
return _this;
}
return TypedError;
}(_wrapNativeSuper(Error));
module.exports = TypedError;

View File

@@ -0,0 +1,348 @@
"use strict";
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
var axios = require('axios');
var apiUrl = 'https://api.cloudflare.com/client/v4'; // Endpoint
var Mailinabox =
/*#__PURE__*/
function () {
function Mailinabox(config) {
_classCallCheck(this, Mailinabox);
this.config = config ? config : {};
if (!this.config.miabHost) {
this.config.miabHost = process.env.MIAB_HOST;
this.config.adminEmail = process.env.MIAB_ADMIN_EMAIL;
this.config.adminPassword = process.env.MIAB_ADMIN_PASSWORD;
}
}
_createClass(Mailinabox, [{
key: "init",
value: function init() {
if (this.config.arrTokens) {
this.zones = [];
}
}
}, {
key: "checkIfParamOk",
value: function checkIfParamOk() {
if (!this.config.miabHost || !this.config.adminEmail || !this.config.adminPassword) {
console.error('Configurazione mancante per il recupero del record DKIM.');
return false;
}
return true;
} // Funzione per ottenere il record DKIM
}, {
key: "getDKIMRecord",
value: function getDKIMRecord(domain) {
var url, auth, response, records, dkimRecord, pattern, match;
return regeneratorRuntime.async(function getDKIMRecord$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
if (this.checkIfParamOk()) {
_context.next = 2;
break;
}
return _context.abrupt("return", '');
case 2:
url = "https://".concat(this.config.miabHost, "/admin/dns/zonefile/").concat(domain);
auth = Buffer.from("".concat(this.config.adminEmail, ":").concat(this.config.adminPassword)).toString('base64');
_context.prev = 4;
_context.next = 7;
return regeneratorRuntime.awrap(axios.get(url, {
headers: {
'Authorization': "Basic ".concat(auth)
}
}));
case 7:
response = _context.sent;
// console.log(`Record DNS esterni per ${config.domain}:`);
// Analizza la risposta per estrarre i record DNS
records = response.data.split('\n').filter(function (line) {
return line.trim() !== '' && !line.startsWith(';');
}).map(function (line) {
return line.trim();
}); // Trova e stampa il record DKIM
dkimRecord = records.find(function (record) {
return record.includes('mail._domainkey');
});
if (!dkimRecord) {
_context.next = 18;
break;
}
pattern = /p=([A-Za-z0-9+/=]+)(?:"\s*"([A-Za-z0-9+/=]+))?/; // Esegui la ricerca
match = dkimRecord.match(pattern);
if (!match) {
_context.next = 17;
break;
}
return _context.abrupt("return", match[1] + (match[2] || ''));
case 17:
console.log('Record DKIM non trovato.');
case 18:
return _context.abrupt("return", '');
case 21:
_context.prev = 21;
_context.t0 = _context["catch"](4);
console.error('Errore nel recupero del record DKIM:', _context.t0.message);
if (_context.t0.response) {
console.error('Dettagli errore:', _context.t0.response.data);
}
case 25:
return _context.abrupt("return", '');
case 26:
case "end":
return _context.stop();
}
}
}, null, this, [[4, 21]]);
}
}, {
key: "MIAB_getEmails",
value: function MIAB_getEmails(myrec) {
var url, auth, response, records;
return regeneratorRuntime.async(function MIAB_getEmails$(_context2) {
while (1) {
switch (_context2.prev = _context2.next) {
case 0:
if (!(!this.checkIfParamOk() || !myrec.domain)) {
_context2.next = 2;
break;
}
return _context2.abrupt("return");
case 2:
url = "https://".concat(this.config.miabHost, "/admin/mail/users?format=text");
auth = Buffer.from("".concat(this.config.adminEmail, ":").concat(this.config.adminPassword)).toString('base64');
_context2.prev = 4;
_context2.next = 7;
return regeneratorRuntime.awrap(axios.get(url, {
headers: {
'Authorization': "Basic ".concat(auth)
}
}));
case 7:
response = _context2.sent;
records = response.data.split('\n').filter(function (line) {
return line.trim() !== '' && line.indexOf(myrec.domain) > -1;
}).map(function (line) {
return line.trim();
});
return _context2.abrupt("return", records);
case 12:
_context2.prev = 12;
_context2.t0 = _context2["catch"](4);
console.error('Errore nel recupero delle Email ', _context2.t0.message);
if (_context2.t0.response) {
console.error('Dettagli errore:', _context2.t0.response.data);
}
case 16:
return _context2.abrupt("return", '');
case 17:
case "end":
return _context2.stop();
}
}
}, null, this, [[4, 12]]);
}
}, {
key: "removeEmail",
value: function removeEmail(myrec) {
var url, auth, myrecout, response, ris;
return regeneratorRuntime.async(function removeEmail$(_context3) {
while (1) {
switch (_context3.prev = _context3.next) {
case 0:
if (!(!this.checkIfParamOk() || !myrec.email)) {
_context3.next = 2;
break;
}
return _context3.abrupt("return");
case 2:
url = "https://".concat(this.config.miabHost, "/admin/mail/users/remove");
auth = Buffer.from("".concat(this.config.adminEmail, ":").concat(this.config.adminPassword)).toString('base64');
_context3.prev = 4;
myrecout = "email=".concat(myrec.email);
_context3.next = 8;
return regeneratorRuntime.awrap(axios.post(url, myrecout, {
headers: {
'Authorization': "Basic ".concat(auth)
}
}));
case 8:
response = _context3.sent;
ris = response.data;
return _context3.abrupt("return", ris);
case 13:
_context3.prev = 13;
_context3.t0 = _context3["catch"](4);
console.error('Errore nella cancellazione della Email ' + record.email, _context3.t0.message);
if (_context3.t0.response) {
console.error('Dettagli errore:', _context3.t0.response.data);
}
case 17:
return _context3.abrupt("return", '');
case 18:
case "end":
return _context3.stop();
}
}
}, null, this, [[4, 13]]);
}
}, {
key: "addEmail",
value: function addEmail(myrec) {
var url, auth, privileges, myrecout, response, ris;
return regeneratorRuntime.async(function addEmail$(_context4) {
while (1) {
switch (_context4.prev = _context4.next) {
case 0:
if (!(!this.checkIfParamOk() || !myrec.email)) {
_context4.next = 2;
break;
}
return _context4.abrupt("return");
case 2:
url = "https://".concat(this.config.miabHost, "/admin/mail/users/add");
auth = Buffer.from("".concat(this.config.adminEmail, ":").concat(this.config.adminPassword)).toString('base64');
_context4.prev = 4;
privileges = myrec.privileges ? 'admin' : '';
myrecout = "email=".concat(myrec.email, "&password=").concat(myrec.pwd, "&privileges=\"").concat(privileges, "\"");
_context4.next = 9;
return regeneratorRuntime.awrap(axios.post(url, myrecout, {
headers: {
'Authorization': "Basic ".concat(auth)
}
}));
case 9:
response = _context4.sent;
ris = response.data;
return _context4.abrupt("return", ris);
case 14:
_context4.prev = 14;
_context4.t0 = _context4["catch"](4);
console.error('Errore nella creazione della Email ' + record.email, _context4.t0.message);
if (_context4.t0.response) {
console.error('Dettagli errore:', _context4.t0.response.data);
}
case 18:
return _context4.abrupt("return", '');
case 19:
case "end":
return _context4.stop();
}
}
}, null, this, [[4, 14]]);
}
}, {
key: "setMailUserPassword",
value: function setMailUserPassword(myrec) {
var url, auth, data, response, ris;
return regeneratorRuntime.async(function setMailUserPassword$(_context5) {
while (1) {
switch (_context5.prev = _context5.next) {
case 0:
if (!(!this.checkIfParamOk() || !myrec.email)) {
_context5.next = 2;
break;
}
return _context5.abrupt("return");
case 2:
url = "https://".concat(this.config.miabHost, "/admin/mail/users/password");
auth = Buffer.from("".concat(this.config.adminEmail, ":").concat(this.config.adminPassword)).toString('base64');
_context5.prev = 4;
data = "email=".concat(myrec.email, "&password=").concat(myrec.pwd);
_context5.next = 8;
return regeneratorRuntime.awrap(axios.post(url, data, {
headers: {
'Authorization': "Basic ".concat(auth),
'Content-Type': 'application/x-www-form-urlencoded'
}
}));
case 8:
response = _context5.sent;
ris = '';
if (response.status === 200) {
ris = "Password cambiata con successo per ".concat(myrec.email);
} else {
ris = "Errore nel cambio password per ".concat(myrec.email);
}
return _context5.abrupt("return", ris);
case 14:
_context5.prev = 14;
_context5.t0 = _context5["catch"](4);
console.error('Errore nella creazione della Email ' + record.email, _context5.t0.message);
if (_context5.t0.response) {
console.error('Dettagli errore:', _context5.t0.response.data);
}
case 18:
return _context5.abrupt("return", '');
case 19:
case "end":
return _context5.stop();
}
}
}, null, this, [[4, 14]]);
}
}]);
return Mailinabox;
}();
module.exports = Mailinabox;

View File

@@ -13,7 +13,7 @@ module.exports = {
try {
const pathfile = Path.join(__dirname, tablename + '.js');
if (tools.isFileExists(pathfile)) {
if (await tools.isFileExistsAsync(pathfile)) {
const mydbfile = require(pathfile);
if (mydbfile && mydbfile.list) {
@@ -39,7 +39,7 @@ module.exports = {
let primavolta = false;
const pathfile = Path.join(__dirname, tablename + '.js');
if (tools.isFileExists(pathfile)) {
if (await tools.isFileExistsAsync(pathfile)) {
const mydbfile = require(pathfile);
if (mydbfile && mydbfile.list) {

View File

@@ -9,7 +9,7 @@ const tools = require('../tools/general');
const Macro = require('../modules/Macro'); // Importa la classe Macro
const fs = require('fs');
const fs = require('fs'); // 👈 Usa il modulo promises
const { City } = require('../models/city');
const Product = require('../models/product');
@@ -27,6 +27,11 @@ const Gasordine = require('../models/gasordine');
const { User } = require('../models/user');
const AmazonBookScraper = require('../modules/Scraping');
const { Catalog } = require('../models/catalog');
const { RaccoltaCataloghi } = require('../models/raccoltacataloghi');
const server_constants = require('../tools/server_constants');
const { ImageDownloader } = require('../tools/general.js');
@@ -55,6 +60,18 @@ const { exec } = require('child_process');
const execPromise = util.promisify(exec);
const GenPdf = require('../modules/GenPdf');
const genPdf = new GenPdf();
let genPdfLaunched = false;
function launchGenPdfIfNeeded() {
if (!genPdfLaunched) {
genPdfLaunched = true;
genPdf.launch();
}
}
async function updateProductInfo(recproductInfoAttuale, product, idapp, mycatstr) {
if (!recproductInfoAttuale || !mycatstr) return recproductInfoAttuale;
@@ -131,15 +148,6 @@ function updateProductInfoCatProds(productInfo, reccatprod) {
}
}
}
async function compressPdf(inputFile, outputFile, compressione) {
try {
const tempFolder = path.join(cwd, 'temp');
const hasTempFolder = tools.isFileExists(tempFolder);
if (!hasTempFolder) {
await fs.mkdir(tempFolder); // Usa la versione promessa di mkdir
}
/*
Quando utilizzi Ghostscript per comprimere un PDF e desideri controllare la qualità di stampa, puoi modificare i parametri dell'opzione -dPDFSETTINGS per ottenere risultati migliori per scopi di stampa.
Le seguenti opzioni sono disponibili per -dPDFSETTINGS:
@@ -152,71 +160,280 @@ async function compressPdf(inputFile, outputFile, compressione) {
/default: Usa impostazioni predefinite; generalmente fornisce un buon equilibrio tra qualità e dimensione.
*/
// Comprime il PDF utilizzando Ghostscript
const gsCommand = `gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/${compressione} -dNOPAUSE -dQUIET -dBATCH -sOutputFile="${outputFile}" "${inputFile}"`;
async function compressPdf(inputFile, outputFile, compressione) {
try {
const tempFolder = path.join(cwd, 'temp');
const hasTempFolder = await tools.isFileExistsAsync(tempFolder);
if (!hasTempFolder) {
console.log('creo directory', tempFolder);
await fs.mkdir(tempFolder); // Usa la versione promessa di mkdir
console.log('✅ directory creata', tempFolder);
}
// Valori ammessi per -dPDFSETTINGS di Ghostscript
const validSettings = ['screen', 'printer', 'high', 'maximum'];
if (!validSettings.includes(compressione)) {
console.warn(`Compressione '${compressione}' non valida, uso 'ebook'`);
compressione = 'ebook';
}
const origSize = await tools.getSizeFile(inputFile);
let add = '';
// Eventualmente......
const in300dpi = false;
if (in300dpi) {
add += '-dDPIx=300 -dDPIy=300';
}
// Costruisci comando Ghostscript per la compressione PDF
const gsCommand = [
'gs',
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
`-dPDFSETTINGS=/${compressione}`,
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
`-sOutputFile="${outputFile}"`,
`"${inputFile}"`,
'-dDownsampleColorImages=true -dColorImageResolution=72',
].join(' ');
console.log('Compressione del PDF in corso...');
console.log('gsCommand', gsCommand);
// Esegui il comando per la compressione
await execPromise(gsCommand);
// Calcola la percentuale di compressione
const newSize = await tools.getSizeFile(outputFile);
const percent = Math.round(((origSize - newSize) / origSize) * 100);
console.log(`Il file compresso è circa il ${percent}% più piccolo dell'originale`);
console.log(`PDF compresso e salvato come '${outputFile}'`);
} catch (error) {
console.error('Errore durante la compressione:', error);
throw error; // Propaga l'errore
}
}
async function convertPDF_GS(inputFile, outputFile, width, height) {
// Verifica che il file di input esista
if (!tools.isFileExists(inputFile)) {
throw new Error(`Il file di input non esiste: ${inputFile}`);
async function compressPdfWithPs2Pdf(inputFile, outputFile, compression = 'ebook') {
try {
// Verifica se il file di input esiste
if (!(await tools.isFileExistsAsync(inputFile))) {
console.error(`Il file di input '${inputFile}' non esiste`);
}
// Converti cm in punti (1 cm = 28.34646 punti)
const widthPt = width * 28.34646;
const heightPt = height * 28.34646;
// Costruisci il comando ps2pdf
const ps2pdfCommand = `ps2pdf -dPDFSETTINGS=/${compression} "${inputFile}" "${outputFile}"`;
// Arrotonda i valori
const widthPx = Math.round(widthPt);
const heightPx = Math.round(heightPt);
console.log(`Eseguendo: ${ps2pdfCommand}`);
// Comando Ghostscript
const gsCommand = [
// Esegui il comando ps2pdf
await execPromise(ps2pdfCommand);
console.log(`PDF compresso con successo: ${outputFile}`);
} catch (error) {
console.error('Errore durante la compressione del PDF:', error);
}
}
// DIAGNOSI COMPLETA DEL PROBLEMA
async function diagnosePDFProblem() {
console.log('=== DIAGNOSI COMPLETA SISTEMA ===');
// 1. Test ambiente Node.js
console.log('Node.js version:', process.version);
console.log('Platform:', process.platform);
console.log('Architecture:', process.arch);
console.log('Current working directory:', process.cwd());
// 2. Test moduli disponibili
try {
console.log('Testing gs module...');
console.log('gs object:', typeof gs, Object.keys(gs || {}));
} catch (error) {
console.log('gs module error:', error.message);
}
// 3. Test comando di sistema
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);
try {
console.log('Testing gs command from system...');
const { stdout, stderr } = await execAsync('gs -version');
console.log('GS Version stdout:', stdout);
console.log('GS Version stderr:', stderr);
} catch (error) {
console.log('System gs command failed:', error.message);
}
// 4. Test scrittura file
const fs = require('fs').promises;
const path = require('path');
const testFile = path.join(process.cwd(), 'test_write.txt');
try {
await fs.writeFile(testFile, 'test content');
console.log('File write test: SUCCESS');
await fs.unlink(testFile);
} catch (error) {
console.log('File write test: FAILED -', error.message);
}
}
// ALTERNATIVA 1: Usando child_process direttamente
async function convertPDF_ChildProcess(inputFile, outputFile, width, height, compressionLevel = 'screen') {
const { spawn } = require('child_process');
const path = require('path');
console.log('=== CONVERSIONE CON CHILD_PROCESS E COMPRESSIONE ===');
// Verifica input
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`File input non trovato: ${inputFile}`);
}
// Assicurati che la directory output esista
const outputDir = path.dirname(outputFile);
const fs = require('fs').promises;
try {
await fs.mkdir(outputDir, { recursive: true });
} catch (error) {
// Directory già esistente, ok
}
// const widthPt = Math.round(width * 28.34646);
// const heightPt = Math.round(height * 28.34646);
const widthPt = Math.round(width * 28.34646 * 10);
const heightPt = Math.round(height * 28.34646 * 10);
// Parametri di compressione ottimizzati
const compressionSettings = {
maximum: [
'-dPDFSETTINGS=/screen',
'-dDownsampleColorImages=true',
'-dColorImageResolution=72',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=72',
'-dDownsampleMonoImages=true',
'-dMonoImageResolution=72',
],
high: [
'-dPDFSETTINGS=/ebook',
'-dDownsampleColorImages=true',
'-dColorImageResolution=150',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=150',
],
printer: ['-dPDFSETTINGS=/printer', '-dDownsampleColorImages=true', '-dColorImageResolution=300'],
screen: [
'-dPDFSETTINGS=/screen',
'-dDownsampleColorImages=true',
'-dColorImageResolution=96',
'-dDownsampleGrayImages=true',
'-dGrayImageResolution=96',
],
};
return new Promise((resolve, reject) => {
const args = [
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
'-dPDFSETTINGS=/prepress',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
`-dDEVICEWIDTHPOINTS=${widthPx}`,
`-dDEVICEHEIGHTPOINTS=${heightPx}`,
'-dDPIx=300',
'-dDPIy=300',
'-dSAFER',
// Parametri di compressione
...(compressionSettings[compressionLevel] || compressionSettings['screen']),
'-dCompressFonts=true',
'-dSubsetFonts=true',
'-dColorImageFilter=/DCTEncode',
'-dGrayImageFilter=/DCTEncode',
'-dEmbedAllFonts=true',
// Dimensioni pagina
`-g${widthPt}x${heightPt}`,
'-dFIXEDMEDIA',
// '-dPDFFitPage',
// Output
`-sOutputFile=${outputFile}`,
inputFile,
].join(' ');
];
console.log('Spawning gs with compression args:', args.join(' '));
const gsProcess = spawn('gs', args, {
stdio: ['ignore', 'pipe', 'pipe'],
shell: process.platform === 'win32',
});
let stdout = '';
let stderr = '';
gsProcess.stdout.on('data', (data) => {
stdout += data.toString();
if (stdout.length < 1000) {
// Evita log troppo lunghi
console.log('GS OUT:', data.toString().trim());
}
});
gsProcess.stderr.on('data', (data) => {
stderr += data.toString();
if (stderr.length < 1000) {
console.log('GS ERR:', data.toString().trim());
}
});
gsProcess.on('close', async (code) => {
console.log(`GS process closed with code: ${code}`);
if (code === 0) {
// Attendi e verifica
setTimeout(async () => {
try {
console.log(gsCommand);
await gs.executeSync(gsCommand); // Assicurati che executeSync restituisca una promessa o usa la funzione corretta se è sincrona.
console.log('Conversione completata con successo!');
const exists = await tools.isFileExistsAsync(outputFile);
if (exists) {
// Verifica dimensioni per confermare compressione
try {
const originalStats = await tools.getFileStatsAsync(inputFile);
const newStats = await tools.getFileStatsAsync(outputFile);
const compressionRatio = (((originalStats.size - newStats.size) / originalStats.size) * 100).toFixed(1);
// Verifica che il file di output sia stato generato
if (tools.isFileExists(outputFile)) {
console.log('File di output generato:', outputFile);
console.log(`📁 File originale: ${(originalStats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`📁 File compresso: ${(newStats.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`🗜️ Compressione: ${compressionRatio}%`);
console.log('✅ SUCCESS: File generato e compresso');
} catch (statsError) {
console.log('Warning: impossibile calcolare statistiche compressione');
}
resolve(outputFile);
} else {
console.error('Il File di output NON è stato generato! :', outputFile);
console.log('❌ FAIL: File non generato nonostante exit code 0');
reject(new Error('File non generato nonostante successo processo'));
}
} catch (error) {
if (error.code === 'ENOENT') {
throw new Error(`Il file di input non esiste: ${inputFile}`);
} else if (error instanceof gs.GhostscriptError) {
throw new Error(`Errore Ghostscript: ${error.message}`);
reject(error);
}
}, 1000);
} else {
throw new Error(`Errore durante la conversione: ${error.message}`);
}
reject(new Error(`Ghostscript failed with code ${code}: ${stderr}`));
}
});
gsProcess.on('error', (error) => {
console.log('GS process error:', error);
reject(new Error(`Failed to start Ghostscript: ${error.message}`));
});
});
}
async function extractPdfInfo(inputFile) {
@@ -249,95 +466,16 @@ async function extractPdfInfo(inputFile) {
}
async function convertPDF_PdfLib(idapp, inputFile, outputFile, options) {
if (!tools.isFileExists(inputFile)) {
if (!(await tools.isFileExistsAsync(inputFile))) {
throw new Error(`Il file di input non esiste: ${inputFile}`);
}
console.log('START convertPDF_PdfLib...');
try {
// Carica il PDF esistente
const existingPdfBytes = fs.readFileSync(inputFile);
const pdfDoc = await PDFDocument.load(existingPdfBytes);
// Crea un nuovo PDF
const newPdfDoc = await PDFDocument.create();
// Itera attraverso le pagine esistenti
const pages = pdfDoc.getPages();
for (const page of pages) {
const { width: originalWidth, height: originalHeight } = page.getSize();
// Calcola la larghezza e l'altezza in punti
const newWidth = options.width * 72; // Convertito in punti
const newHeight = options.height * 72; // Convertito in punti
// Crea una nuova pagina con le dimensioni specificate
const newPage = newPdfDoc.addPage([newWidth, newHeight]);
// Calcola lo scaling per mantenere le proporzioni
const scaleWidth = newWidth / originalWidth;
const scaleHeight = newHeight / originalHeight;
const scale = Math.min(scaleWidth, scaleHeight); // Usa il min per mantenere il rapporto
// Incorpora la pagina esistente nel nuovo PDF
const embeddedPage = await newPdfDoc.embedPage(page);
// Disegna la pagina incorporata nel nuovo PDF
newPage.drawPage(embeddedPage, {
x: (newWidth - originalWidth * scale) / 2, // Centrato orizzontalmente
y: (newHeight - originalHeight * scale) / 2, // Centrato verticalmente
width: originalWidth * scale,
height: originalHeight * scale,
});
}
// Salva il nuovo PDF
const pdfBytes = await newPdfDoc.save();
fs.writeFileSync(outputFile, pdfBytes);
console.log(`PDF convertito e salvato come '${outputFile}'`);
const comprimi = false;
const mostrainfo = true;
let fileout = outputFile;
if (options.compressione) {
const todayDate = tools.getDateYYYYMMDD_Today();
const compressed = tools.removeFileExtension(outputFile) + `_${todayDate}.pdf`;
await compressPdf(outputFile, compressed, options.compressione);
if (mostrainfo) extractPdfInfo(compressed);
fileout = compressed;
}
if (options.dir_out && options.idapp) {
// Crea directory se non esiste !
// Salva il fileout anche su questa directory dir_out
//const fileoutdir = path.join(options.dir_out, options.file_out);
//await fs.promises.copyFile(fileout, fileoutdir);
//console.log(`File ${fileout} anche salvato in ${options.dir_out}`);
}
let fileout_print = '';
// Crea anche il PDF per la stampa
if (
options.print_left !== 0 ||
options.print_top !== 0 ||
options.print_right !== 0 ||
options.print_bottom !== 0
) {
options.filenameIn = fileout;
ris = await ConvertPDF_WithMargins(options);
}
const uscita = {
pdf_generato: tools.removePathDirByFileName(options.idapp, fileout),
pdf_generato_stampa: tools.removePathDirByFileName(options.idapp, ris.fileout_print),
}
options.filenameIn = inputFile;
options.filenameOut = outputFile;
const uscita = await ConvertPDF_Generatore(options, options.stampa);
return uscita;
} catch (e) {
@@ -345,20 +483,57 @@ async function convertPDF_PdfLib(idapp, inputFile, outputFile, options) {
return '';
}
}
async function ConvertPDF_WithMargins(options) {
let fileout_print = '';
const marginTop = parseFloat(options.print_top) || 0;
const marginRight = parseFloat(options.print_right) || 0;
const marginBottom = parseFloat(options.print_bottom) || 0;
const marginLeft = parseFloat(options.print_left) || 0;
async function leggiDimensioniPdf(filePath) {
const pdfBytes = await fs.promises.readFile(filePath);
const pdfDoc = await PDFDocument.load(pdfBytes);
if (!options.filenameIn) {
return { err: 'Nessun file caricato.' };
const pages = pdfDoc.getPages();
const primaPagina = pages[0];
const { width, height } = primaPagina.getSize();
console.log(
`Dimensioni prima pagina: larghezza = ${tools.arrotondaA2Decimali(
(width / 72) * 25.4
)} mm, altezza = ${tools.arrotondaA2Decimali((height / 72) * 25.4)} mm`
);
return { width, height };
}
const outputFilename = path.basename(tools.removeFileExtension(options.filenameIn))+ '-stampabile.pdf';
const outputPath = path.join(options.dir_out, outputFilename);
async function ConvertPDF_Generatore(options, instampa) {
let fileout = '';
let fileout_compressed = '';
let suffisso_filename = '';
if (!options.filenameIn) {
return { err: 'Nessun file passato in Ingresso.' };
}
let marginTop = instampa ? parseFloat(options.print_top) : 0;
let marginRight = instampa ? parseFloat(options.print_right) : 0;
let marginBottom = instampa ? parseFloat(options.print_bottom) : 0;
let marginLeft = instampa ? parseFloat(options.print_left) : 0;
if (instampa) {
suffisso_filename = '_stampabile_generato';
} else {
suffisso_filename = '_generato';
}
let outputFilename = suffisso_filename
? tools.aggiungiSuffissoAlNomeFile(options.filenameOut, suffisso_filename)
: options.filenameOut;
// controlla se outputFilename non ha directory allora gliela aggiungo
if (!path.dirname(outputFilename)) {
outputFilename = path.join(options.dir_out, outputFilename);
}
const outputFullPathFileName = outputFilename;
await leggiDimensioniPdf(options.filenameIn);
try {
// Leggi il PDF originale
@@ -370,8 +545,12 @@ async function ConvertPDF_WithMargins(options) {
for (let i = 0; i < pages.length; i++) {
const page = pages[i];
// punti PDF (pt), dove 1 punto = 1/72 di pollice.
const { width, height } = page.getSize();
// CONVERTIli in mm e stampa su console
console.log(`Dimensione pagina ${i + 1}: ${(width / 72) * 25.4} mm x ${(height / 72) * 25.4} mm`);
const newWidth = width - marginLeft - marginRight;
const newHeight = height - marginTop - marginBottom;
@@ -394,21 +573,232 @@ async function ConvertPDF_WithMargins(options) {
// Salva il nuovo PDF
const pdfBytes = await destPdfDoc.save();
await fs.promises.mkdir(options.dir_out, { recursive: true });
const dirUscita = path.dirname(outputFullPathFileName);
if (!(await tools.isDirectoryAsync(dirUscita))) {
await fs.promises.mkdir(dirUscita, { recursive: true });
}
await fs.promises.writeFile(outputPath, pdfBytes);
await fs.promises.writeFile(outputFullPathFileName, pdfBytes);
fileout = outputFullPathFileName;
extractPdfInfo(fileout);
fileout_print = outputPath;
// Elimina il file compresso precedente...
fileOLD_compressed = tools.removeFileExtension(fileout) + `_compressed.pdf`;
if (await tools.isFileExistsAsync(fileOLD_compressed)) {
await tools.deleteFile(fileOLD_compressed);
}
if (options.compressione) {
const mostrainfo = true;
fileout_compressed = tools.removeFileExtension(fileout) + `_compressed.pdf`;
await diagnosePDFProblem();
// await compressPdf(fileout, fileout_compressed, options.compressione);
// await compressPdfWithPs2Pdf(fileout, fileout_compressed, options.compressione);
await convertPDF_ChildProcess(fileout, fileout_compressed, options.width, options.height, options.compressione);
// if (mostrainfo) extractPdfInfo(fileout_compressed);
}
} catch (error) {
const log = 'Errore durante la creazione del PDF per la Stampa:' + error.message;
const log = `Errore durante la creazione del PDF: (instampa = ${instampa}): ` + error.message;
console.error(log);
return { err: log, fileout_print: '' };
return {
err: log,
fileout: tools.removePathDirByFileName(options.idapp, fileout),
fileout_compressed: tools.removePathDirByFileName(options.idapp, fileout_compressed),
};
}
return { fileout_print };
return {
fileout: tools.removePathDirByFileName(options.idapp, fileout),
fileout_compressed: tools.removePathDirByFileName(options.idapp, fileout_compressed),
filesize: await tools.getSizeFile(fileout),
filesize_compressed: fileout_compressed ? await tools.getSizeFile(fileout_compressed) : 0,
};
}
router.post('/online-pdf', authenticate, async (req, res) => {
console.log('/online-pdf');
try {
launchGenPdfIfNeeded(); // Ensure GenPdf is launched before proceeding
const risout = await GenPdf.onlinePdf(req.body);
return res.status(200).send(risout);
} catch (e) {
console.error('Err Online-pdf', e.message);
}
});
async function JoinPDFCatalogs(raccolta, cataloghi, options, outputFile, stampa) {
try {
// Per ogni catalogo prendi il suo PDF Generato
const pdfDoc = await PDFDocument.create();
let numcat = 0;
// Aggiungi eventuale PDF di copertina
if (raccolta.pdf_copertina) {
let dirmain = '';
if (!tools.sulServer()) {
dirmain = server_constants.DIR_PUBLIC_LOCALE;
}
const myfile = tools.fixFilePath(
path.join(options.mydir + dirmain + '/' + options.dir_out, raccolta.pdf_copertina?.imagefile)
);
console.log(' copertina: ' + myfile);
if (await tools.isFileExistsAsync(myfile)) {
const pdfBytes = await fs.promises.readFile(myfile);
const pdf = await PDFDocument.load(pdfBytes);
const pages = pdf.getPages();
const copiedPages = await pdfDoc.copyPages(
pdf,
pages.map((p, i) => i)
);
for (let page of copiedPages) {
pdfDoc.addPage(page);
}
console.log(' Aggiungo la copertina ' + myfile);
}
}
for (let id_catalog of cataloghi) {
let catalog = await Catalog.findOne({ _id: id_catalog });
if (catalog) {
let filename = stampa ? catalog.pdf_online_stampa : catalog.pdf_online;
if (filename) {
let myfile = tools.fixFilePath(options.mydir + '/' + filename);
if (await tools.isFileExistsAsync(myfile)) {
const filenameOnly = path.parse(myfile).base;
numcat++;
console.log(' Aggiungo il catalogo [' + numcat + '] ' + filenameOnly + ' ...');
const pdfBytes = await fs.promises.readFile(myfile);
const pdf = await PDFDocument.load(pdfBytes);
const pages = pdf.getPages();
const copiedPages = await pdfDoc.copyPages(
pdf,
pages.map((p, i) => i)
);
for (let page of copiedPages) {
pdfDoc.addPage(page);
}
}
} else {
console.log('ATTENZIONE! Catalogo non ancora Generato ! ', catalog.title);
}
}
}
// Raccolta salvata !
const pdfBytes = await pdfDoc.save();
await fs.promises.writeFile(outputFile, pdfBytes);
// scrivi il percorso relativo e nomefile sul DB
const outputFilename = path.basename(outputFile);
const outputPath = path.join(options.dir_out, outputFilename);
if (await tools.isFileExistsAsync(outputFile)) {
console.log('✅ Catalogo Completo Generato correttamente ! ', outputFile);
} else {
console.log('❌ Catalogo non generato ! ', outputFile);
}
const ris = {
outputPath,
};
return ris;
} catch (e) {
console.error('Error: ', e);
}
return {};
}
router.post('/join-pdf', authenticate, async (req, res) => {
console.log('/join-pdf');
idapp = req.body.idapp;
options = req.body.options;
options.idapp = idapp;
options.mydir = tools.getdirByIdApp(idapp);
try {
const mydirpath = tools.getdirByIdApp(options.idapp);
const full_dir_out = tools.fixFilePath(path.join(mydirpath, options.dir_out));
await fs.promises.mkdir(full_dir_out, { recursive: true });
// Aggiorna il PDF OnLine, copiando il file da Generato a OnLine
let raccolta = await RaccoltaCataloghi.findOne({ _id: options.id_raccolta });
if (raccolta && raccolta.nomefile_da_generare) {
cataloghi = raccolta.lista_cataloghi;
let outputFile = path.join(
full_dir_out,
tools.removeFileExtension(raccolta.nomefile_da_generare) + '_generato.pdf'
);
if (options.stampa) {
outputFileStampa =
path.join(full_dir_out, path.basename(tools.removeFileExtension(outputFile))) + '_stampabile.pdf';
// Creazione file per STAMPA
const ris_stampa = await JoinPDFCatalogs(raccolta, cataloghi, options, outputFileStampa, true);
if (ris_stampa) {
raccolta.pdf_generato_stampa = ris_stampa.outputPath;
let myfilecheckstampa = path.join(mydirpath, ris_stampa.outputPath);
raccolta.pdf_generato_stampa_size = await tools.getSizeFile(myfilecheckstampa);
raccolta.data_generato_stampa = tools.getDateNow();
}
} else {
// Creazione file per WEB
const ris = await JoinPDFCatalogs(raccolta, cataloghi, options, outputFile, false);
if (ris) {
raccolta.pdf_generato = ris.outputPath;
let myfilecheck = path.join(mydirpath, ris.outputPath);
raccolta.pdf_generato_size = await tools.getSizeFile(myfilecheck);
raccolta.data_generato = tools.getDateNow();
}
}
if (options.metti_online) {
if (options.stampa) {
raccolta.pdf_online_stampa = raccolta.pdf_generato_stampa.replace('_generato', '');
} else {
raccolta.pdf_online = raccolta.pdf_generato.replace('_generato', '');
}
const fileDest = options.mydir + raccolta.pdf_online;
await fs.promises.writeFile(fileDest, pdfBytes);
let size = await tools.getSizeFile(FileDest);
if (options.stampa) {
raccolta.pdf_online_stampa_size = size;
} else {
raccolta.pdf_online_size = size;
}
}
await raccolta.save();
risout = { raccolta: raccolta._doc };
}
// risout
return res.status(200).send(risout);
} catch (e) {
console.error('Err join-pdf', e.message);
}
});
// Endpoint POST per la conversione del PDF
router.post('/convert-pdf', upload.single('pdf'), async (req, res) => {
if (!req.file) {
@@ -427,76 +817,76 @@ router.post('/convert-pdf', upload.single('pdf'), async (req, res) => {
print_right = '0',
print_bottom = '0',
print_left = '0',
stampa,
salvasufiledascaricare = 'false',
} = req.body;
if (!width) {
await fs.promises.unlink(inputFile);
return res.status(400).send('Width parameter is required');
}
const options = {
width,
height,
compressione,
dir_out,
dir_out: tools.getdirByIdApp(idapp) + '/' + dir_out,
file_out,
idapp,
print_top,
print_right,
print_bottom,
print_left,
stampa: stampa === '1',
};
if (!width) {
fs.unlinkSync(inputFile);
return res.status(400).send('Width parameter is required');
let invia_file_convertito = false;
if (!options.file_out || options.file_out === '') {
options.file_out = `${tools.removeFileExtension(req.file.originalname)}-converted.pdf`;
invia_file_convertito = true;
}
options.dir_out = tools.getdirByIdApp(options.idapp) + '/' + options.dir_out;
// let outputFile = path.join(options.dir_out, `${tools.removeFileExtension(req.file.originalname)}-converted.pdf`);
let outputFile = path.join(options.dir_out, `${options.file_out}`);
let outputFile = path.join(options.dir_out, options.file_out);
try {
await fs.promises.mkdir(DIR_PDF_IN, { recursive: true });
await fs.promises.mkdir(options.dir_out, { recursive: true });
// Converti il PDF
// await convertPDF_GS(inputFile, outputFile, width, height);
const risout = await convertPDF_PdfLib(idapp, inputFile, outputFile, options);
if (!options.dir_out) {
// Invia il file convertito
res.download(risout.pdf_generato, 'output-converted.pdf', (err) => {
if (salvasufiledascaricare === 'true') {
// Invia il file come download
return res.download(outputFile, options.file_out, async (err) => {
await cleanupFiles(inputFile, outputFile);
if (err) {
if (err.code === 'ECONNABORTED' || err.code === 'ECONNRESET') {
console.warn('Richiesta annullata dal client:', err.message);
return;
}
console.error("Errore durante l'invio del file:", err.message || err);
if (!res.headersSent) {
res.status(500).send("Errore durante l'invio del file convertito");
}
} else {
// Rimuovi i file temporanei
cleanupFiles(inputFile, '');
}
});
} else {
cleanupFiles(inputFile, '');
}
// Non inviare file, solo risposta JSON
await cleanupFiles(inputFile, ''); // pulisci solo inputFile
return res.status(200).send(risout);
}
} catch (error) {
console.error('Errore durante la conversione:', error);
cleanupFiles(inputFile, '');
await cleanupFiles(inputFile, '');
if (!res.headersSent) {
res.status(500).send(`Errore durante la conversione del PDF: ${error.message}`);
return res.status(500).send(`Errore durante la conversione del PDF: ${error.message}`);
}
}
});
function cleanupFiles(inputFile, outputFile) {
async function cleanupFiles(inputFile, outputFile) {
if (inputFile) {
tools.deleteFile(inputFile).catch((err) => {
await tools.deleteFile(inputFile).catch((err) => {
console.error('Errore durante la rimozione del file di INPUT:', err);
});
}
if (outputFile) {
tools.deleteFile(outputFile).catch((err) => {
await tools.deleteFile(outputFile).catch((err) => {
console.error('Errore durante la rimozione del file di output:', err);
});
}
@@ -797,6 +1187,7 @@ router.post('/import', authenticate, async (req, res) => {
if (recmacro.ean && recmacro.ean['#text']) {
recmacro._id = recmacro.ean['#text'];
recmacro.code = recmacro._id;
recmacro.title = getvalueByJsonText(recmacro.titolo);
let queryprod = { idapp, code: recmacro._id };
@@ -2184,6 +2575,32 @@ router.post('/cloudflare', authenticate, async (req, res) => {
}
});
router.post('/scraper', authenticate, async (req, res) => {
idapp = req.body.idapp;
idProduct = req.body.product_id;
options = req.body.options;
const scraper = new AmazonBookScraper();
const product = await Product.getProductById(idProduct);
let isbn = '';
if (product) {
isbn = product.isbn;
}
try {
let data = null;
if (isbn) {
data = await scraper.scrapeISBN(product, isbn, options);
console.log(data);
}
return res.send(data);
} catch (e) {
console.error(e);
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: '' });
}
});
router.post('/miab', authenticate, async (req, res) => {
try {
idapp = req.body.idapp;
@@ -2222,4 +2639,21 @@ router.post('/miab', authenticate, async (req, res) => {
}
});
router.post('/generate-pdf', async (req, res) => {
const { url, filename } = req.body;
if (!url || !filename) {
return res.status(400).json({ error: 'url e filename sono richiesti' });
}
try {
launchGenPdfIfNeeded(); // Ensure GenPdf is launched before proceeding
const pdfPath = await genPdf.generatePdfFromUrl(url, filename);
res.download(pdfPath);
} catch (error) {
console.error('Errore generazione PDF:', error);
res.status(500).json({ error: 'Errore generazione PDF' });
}
});
module.exports = router;

View File

@@ -21,14 +21,13 @@ const globalTables = require('../tools/globalTables');
const { ObjectId } = require('mongodb');
const OpenAI = require("openai");
const OpenAI = require('openai');
const { PassThrough } = require('stream');
const { spawn } = require('child_process');
router.post('/getlist', authenticate_noerror, async function (req, res, next) {
try {
let idapp = req.body.idapp;
@@ -36,26 +35,23 @@ router.post('/getlist', authenticate_noerror, async function (req, res, next) {
return res.send({
code: server_constants.RIS_CODE_OK,
queryAIList
queryAIList,
});
} catch (e) {
console.error('/getlist', e);
}
return null;
});
async function getDeepSeekResponse(prompt, options) {
try {
const deepseek = new OpenAI({
baseURL: 'https://api.deepseek.com/v1',
apiKey: process.env.DS_API_KEY,
defaultHeaders: {
'Content-Type': 'application/json'
}
'Content-Type': 'application/json',
},
});
if (!options.withexplain) {
@@ -66,10 +62,10 @@ async function getDeepSeekResponse(prompt, options) {
}
const completionStream = await deepseek.chat.completions.create({
model: options.model || "deepseek-chat",
model: options.model || 'deepseek-chat',
messages: [
{ role: "system", content: options?.contestsystem || "" },
{ role: "user", content: prompt }
{ role: 'system', content: options?.contestsystem || '' },
{ role: 'user', content: prompt },
],
temperature: options?.temp || 0.3,
max_tokens: options?.max_tokens || 1000,
@@ -101,10 +97,87 @@ async function getDeepSeekResponse(prompt, options) {
}
router.post('/ds', authenticate, async (req, res) => {
const { prompt, options } = req.body;
const isstream = (options && options?.stream)
const isollama = options.model.startsWith('gemma3');
if (isollama) {
// Endpoint per generare una risposta dal modello Ollama
const { prompt } = req.body;
// const model = "phi:3.8b-mini-4k"; // Modello predefinito
const model = options.model;
if (!prompt) {
return res.status(400).json({ error: 'Il prompt è richiesto.' });
}
try {
// Chiamata all'API di Ollama
const ollama = spawn('curl', [
'-X',
'POST',
'http://localhost:11434/api/generate',
'-H',
'Content-Type: application/json',
'-d',
JSON.stringify({
model: model,
prompt: prompt,
stream: false, // Imposta a true se vuoi una risposta in streaming
}),
]);
let data = '';
let error = '';
ollama.stdout.on('data', (chunk) => {
data += chunk;
});
ollama.stderr.on('data', (chunk) => {
error += chunk;
});
ollama.on('close', (code) => {
if (code !== 0) {
console.error(`Errore Ollama: ${error}`);
return res.status(500).json({ error: 'Errore nella generazione del modello.' });
}
try {
// Ollama restituisce una risposta JSON
const response = JSON.parse(data);
const risp = response?.error ? response?.error : response?.response;
//res.json({ response: response.response }); // Invia solo la risposta al frontend
if (response?.error) {
return res.send({
code: server_constants.RIS_CODE_ERR,
error: risp,
});
} else {
return res.send({
code: server_constants.RIS_CODE_OK,
choice: risp,
});
}
} catch (parseError) {
console.error('Errore nel parsing della risposta di Ollama:', parseError);
return res.send({
code: server_constants.RIS_CODE_ERR,
error: 'Errore nella risposta del modello.',
});
}
});
} catch (err) {
console.error(err);
return res.send({
code: server_constants.RIS_CODE_ERR,
error: 'Errore interno del server.',
});
}
} else {
const isstream = options && options?.stream;
if (isstream) {
// Se lo streaming è abilitato, restituiamo un flusso di dati
@@ -134,10 +207,8 @@ router.post('/ds', authenticate, async (req, res) => {
res.write('data: [DONE]\n\n');
res.end();
} catch (error) {
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
const errorstr = 'API Error:' + (error.response?.data || error.message);
console.error(errorstr);
// In caso di errore durante lo streaming, invia un messaggio di errore
@@ -147,7 +218,6 @@ router.post('/ds', authenticate, async (req, res) => {
});
res.write(`data: ${errorData}\n\n`);
res.end();
}
} else {
try {
@@ -159,7 +229,7 @@ router.post('/ds', authenticate, async (req, res) => {
choice,
});
} catch (error) {
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
const errorstr = 'API Error:' + (error.response?.data || error.message);
console.error(errorstr);
// In caso di errore senza streaming, restituisci un errore standard
@@ -169,6 +239,7 @@ router.post('/ds', authenticate, async (req, res) => {
});
}
}
}
});
module.exports = router;

View File

@@ -0,0 +1,473 @@
const express = require('express');
const { authenticate, authenticate_noerror } = require('../middleware/authenticate');
const router = express.Router();
const PageView = require('../models/PageView');
const multer = require('multer');
const XLSX = require('xlsx');
const upload = multer({ dest: 'uploads/' });
const Product = require('../models/product');
const ProductInfo = require('../models/productInfo');
const Author = require('../models/author');
const tools = require('../tools/general');
const axios = require('axios');
router.post('/test-lungo', authenticate, (req, res) => {
const timeout = req.body.timeout;
console.log(`🕙 Richiesta iniziata con timeout=${timeout}`);
// Simuliamo un'elaborazione lunga
const durataMs = timeout - 2000;
setTimeout(() => {
console.log(`✅ Elaborazione completata di ${durataMs} ms`);
res.json({ ok: true, message: `✅ Richiesta completata con successo! (${durataMs})` });
}, durataMs);
// Verifico se la richiesta va a buon fine
setTimeout(() => {
if (!res.headersSent) {
res.status(500).json({ ok: false, message: "❌ Errore durante l'elaborazione della richiesta!" });
}
}, durataMs + 1000);
});
router.post('/track-pageview', authenticate_noerror, async (req, res) => {
const { url, userAgent, idapp, referrer } = req.body;
const ip = req.ip || req.headers['x-forwarded-for'] || 'unknown';
try {
const pageView = new PageView({
url,
ip,
idapp,
referrer,
userId: req.user ? req.user._id : '',
username: req.user ? req.user.username : '',
userAgent,
});
await pageView.save();
res.status(200).json({ message: '' });
} catch (error) {
console.error('Errore nel salvataggio della visita:', error);
res.status(500).json({ error: 'Impossibile registrare la visita' });
}
});
router.get('/pageviews/stats', authenticate_noerror, async (req, res) => {
const { userId, idapp, unique } = req.query;
try {
const matchStage = { idapp };
if (userId) {
matchStage.$or = [{ userId }, { username: userId }];
}
// Definiamo la base della pipeline
const basePipeline = [{ $match: matchStage }];
const today = startOfDay(new Date());
const weekAgo = startOfDay(subDays(new Date(), 7));
const monthAgo = startOfDay(subDays(new Date(), 30));
// Funzione dinamica per creare pipeline di conteggio
const countStage = (date) => {
const match = { timestamp: { $gte: date } };
if (!unique) {
return [{ $match: match }, { $count: 'count' }];
}
return [
{ $match: match },
{
$group: {
_id: {
url: '$url',
user: { $ifNull: ['$userId', '$ip'] },
date: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
},
},
},
{ $count: 'count' },
];
};
// Pipeline completa
const timeStatsPipeline = [
...basePipeline,
{
$facet: {
total: !unique
? [{ $count: 'count' }]
: [
{
$group: {
_id: {
url: '$url',
user: { $ifNull: ['$userId', '$ip'] },
date: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
},
},
},
{ $count: 'count' },
],
today: countStage(today),
week: countStage(weekAgo),
month: countStage(monthAgo),
},
},
];
// Eseguiamo solo la parte delle statistiche temporali
const timeStatsResult = await PageView.aggregate(timeStatsPipeline);
// Ora costruiamo la pipeline completa per topPages (con o senza unique)
let topPagesPipeline = [...basePipeline];
if (unique) {
topPagesPipeline = [
...topPagesPipeline,
{
$group: {
_id: {
url: '$url',
userId: { $ifNull: ['$userId', '$ip'] },
date: {
$dateToString: {
format: '%Y-%m-%d',
date: '$timestamp',
},
},
},
},
},
{ $replaceRoot: { newRoot: '$_id' } },
];
}
// Aggiungi il group finale per contare le pagine
const topPagesResult = await PageView.aggregate([
...topPagesPipeline,
{
$group: {
_id: '$url',
count: { $sum: 1 },
},
},
{ $sort: { count: -1 } },
{ $limit: 10 },
]);
// Formattazione dei risultati
const formatCount = (arr) => (arr && arr.length > 0 ? arr[0].count || 0 : 0);
const stats = {
total: formatCount(timeStatsResult[0]?.total),
today: formatCount(timeStatsResult[0]?.today),
week: formatCount(timeStatsResult[0]?.week),
month: formatCount(timeStatsResult[0]?.month),
topPages: topPagesResult,
};
res.json(stats);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Errore nel calcolo delle statistiche' });
}
});
function startOfDay(date) {
return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}
function subDays(date, days) {
const newDate = new Date(date);
newDate.setDate(newDate.getDate() - days);
return newDate;
}
router.get('/pageviews/users', authenticate_noerror, async (req, res) => {
try {
const { idapp } = req.query;
// Trova tutte le entry con idapp e prendi userId e username
const usersData = await PageView.find({ idapp }, { userId: 1, username: 1, _id: 0 }).lean();
// Usa un Map per garantire unicità basata su userId
const uniqueUsersMap = new Map();
usersData.forEach(({ userId, username }) => {
if (userId && !uniqueUsersMap.has(userId)) {
uniqueUsersMap.set(userId, { userId, username });
}
});
// Converte la Map in array
const uniqueUsers = Array.from(uniqueUsersMap.values());
res.json(uniqueUsers);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Errore nel recupero degli utenti' });
}
});
router.get('/pageviews/weekly-top-pages', authenticate_noerror, async (req, res) => {
const { idapp, userId, unique, year, week } = req.query;
try {
const matchStage = { idapp };
if (userId) {
matchStage.$or = [{ userId }, { username: userId }];
}
const pipeline = [];
// Filtro base
pipeline.push({ $match: matchStage });
// Estrai settimana e anno
pipeline.push({
$addFields: {
week: { $isoWeek: '$timestamp' },
year: { $isoWeekYear: '$timestamp' },
},
});
// Filtra per settimana e anno se specificati
if (year && week) {
pipeline.push({
$match: {
year: parseInt(year),
week: parseInt(week),
},
});
}
if (unique === 'true') {
// Visite uniche: 1 per utente/giorno/pagina
pipeline.push({
$group: {
_id: {
url: '$url',
user: { $ifNull: ['$userId', '$ip'] },
day: { $dateToString: { format: '%Y-%m-%d', date: '$timestamp' } },
},
},
});
// Riformatta per conteggio
pipeline.push({
$group: {
_id: '$_id.url',
count: { $sum: 1 },
},
});
} else {
// Visite totali: tutte le occorrenze
pipeline.push({
$group: {
_id: '$url',
count: { $sum: 1 },
},
});
}
// Ordina per numero visite
pipeline.push({ $sort: { count: -1 } });
// Aggiungi metadati settimana/anno se presenti
if (year && week) {
pipeline.push({
$addFields: {
year: parseInt(year),
week: parseInt(week),
},
});
}
const result = await PageView.aggregate(pipeline);
res.json(
result.map((r) => ({
url: r._id,
count: r.count,
year: r.year,
week: r.week,
}))
);
} catch (err) {
console.error(err);
res.status(500).json({ error: 'Errore nel calcolo delle statistiche settimanali' });
}
});
router.post('/api/convert-csv-to-xls', upload.single('csv'), (req, res) => {
try {
const csvFilePath = req.file.path;
// Leggi il CSV con SheetJS
const csvData = fs.readFileSync(csvFilePath, 'utf-8');
const worksheet = XLSX.utils.csv_to_sheet(csvData);
// Crea un file Excel
const workbook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workbook, worksheet, 'Sheet1');
// Imposta la risposta come file XLS
const xlsFilePath = path.join(__dirname, 'converted', 'output.xls');
XLSX.writeFile(workbook, xlsFilePath);
// Restituisci il file XLS al frontend come risposta
res.download(xlsFilePath, 'converted-file.xls', (err) => {
if (err) {
console.error('Errore nel download del file:', err);
res.status(500).send('Errore nel download del file');
}
// Pulisci il file temporaneo
fs.unlinkSync(csvFilePath);
fs.unlinkSync(xlsFilePath);
});
} catch (error) {
console.error('Errore nella conversione del file:', error);
res.status(500).send('Errore nella conversione del file');
}
});
// Funzione per "escapare" i caratteri speciali
const escapeRegExp = (string) => {
return string.replace(/[.*+?^=!:${}()|\[\]\/\\]/g, '\\$&'); // Escape dei caratteri speciali
};
// API per la ricerca dei libri
router.post('/search-books', authenticate, async (req, res) => {
const { books } = req.body;
if (!books || books.length === 0) {
return res.status(400).json({ error: 'Nessun dato fornito per la ricerca' });
}
try {
// Crea un array per raccogliere i risultati
let results = [];
let product = null;
for (const book of books) {
let trovatoISBN = false;
let trovato = false;
for (let field of book) {
field = field.trim();
let valido = typeof field === 'string' && field.length > 4 && field.length < 50;
if (valido) {
// Cerca il primo record che corrisponde per ISBN o titolo
if (true) {
if (!trovatoISBN) {
let productInfoarrISBN = await ProductInfo.find({
code: field.toUpperCase(),
$or: [{ deleted: false }, { deleted: { $exists: false } }],
}).exec();
// Priorità se lo trovo per ISBN:
if (productInfoarrISBN.length === 1) {
productInfo = productInfoarrISBN[0];
trovatoISBN = true;
trovato = true;
}
}
if (!trovatoISBN && !trovato) {
// Prima cerca se è esattamente cosi
let productInfoarrTitle = await ProductInfo.find({
$or: [{ deleted: false }, { deleted: { $exists: false } }],
name: field,
}).exec();
if (productInfoarrTitle.length === 1) {
productInfo = productInfoarrTitle[0];
trovato = true;
} else {
if (productInfoarrTitle.length > 1) {
// Prendi l'Ultimo !
productInfo = productInfoarrTitle[productInfoarrTitle.length - 1];
trovato = true;
}
}
if (!trovato) {
// Altrimenti per Titolo
productInfoarrTitle = await ProductInfo.find({
$or: [{ deleted: false }, { deleted: { $exists: false } }],
name: new RegExp(`.*${escapeRegExp(tools.removeAccents(field.toUpperCase()))}.*`, 'i'),
}).exec();
if (productInfoarrTitle.length === 1) {
productInfo = productInfoarrTitle[0];
trovato = true;
} else {
if (productInfoarrTitle.length > 1) {
// Prendi l'Ultimo !
productInfo = productInfoarrTitle[productInfoarrTitle.length - 1];
trovato = true;
}
}
}
}
}
}
}
if (trovato) {
if (productInfo) {
product = await Product.findOne({ idProductInfo: productInfo._id }).exec();
if (product) {
const existingResult = results.find((r) => r._id.toString() === product._id.toString());
if (!existingResult) {
let titolo = productInfo.name;
results.push({
...product,
productInfo,
_id: product._id,
title: titolo,
isbn: product.isbn,
authors: await Promise.all(
productInfo.idAuthors.map(async (authorId) => {
const author = await Author.findById(authorId).exec();
return author ? `${author.name} ${author.surname}`.trim() : '';
})
),
select: true,
});
}
}
}
}
//
}
res.status(200).json(results); // Restituisci i risultati trovati
} catch (err) {
console.error('Errore durante la ricerca dei libri:', err);
res.status(500).json({ error: 'Errore interno del server' });
}
});
router.post('/chatbot', authenticate, async (req, res) => {
try {
const response = await axios.post('http://localhost:5005/webhooks/rest/webhook', {
sender: 'user',
message: req.body.payload.message,
});
res.json(response.data);
} catch (error) {
console.error(error?.message);
res.status(500).send('Errore nella comunicazione con Rasa');
}
});
module.exports = router;

View File

@@ -10,6 +10,8 @@ var server_constants = require('../tools/server_constants');
var { Project } = require('../models/project');
const Scontistica = require('../models/scontistica');
var { authenticate, auth_default } = require('../middleware/authenticate');
const _ = require('lodash');
@@ -28,26 +30,44 @@ const paypal_config = require('../configs/paypal-config')
const paypal = require('paypal-rest-sdk')
*/
const CartClass = require('../modules/Cart')
const CartClass = require('../modules/Cart');
const Cart = require('../models/cart');
const OrdersCart = require('../models/orderscart');
//GET cart
router.get('/:userId', authenticate, async function (req, res, next) {
let userId = req.params.userId
let idapp = req.user.idapp
let userId = req.params.userId;
let idapp = req.user.idapp;
return await Cart.getCartByUserId(userId, idapp)
.then((cart) => {
if (cart)
return res.send({ code: server_constants.RIS_CODE_OK, cart });
else
return res.send({ code: server_constants.RIS_CODE_OK, cart: null });
}).catch((err) => {
if (cart) return res.send({ code: server_constants.RIS_CODE_OK, cart });
else return res.send({ code: server_constants.RIS_CODE_OK, cart: null });
})
.catch((err) => {
console.error('Err', err);
return res.send({ code: server_constants.RIS_CODE_ERR, cart: null });
});
});
})
async function aggiornaCarrello(mycartpar, userId, idapp) {
try {
let mycart = mycartpar;
if (!mycart) mycart = await Cart.getCartByUserId(userId, idapp);
if (!mycart) return null;
mycart = await Cart.getCartCompletoByCartId(mycart._id, idapp);
let newCart = await CartClass.constructByCart(mycart);
if (newCart) return newCart.aggiornaCarrello();
return newCart;
} catch (e) {
console.error('Err AggiornaCarrello', e);
return null;
}
}
//POST cart
router.post('/:userId', authenticate, async function (req, res, next) {
@@ -60,14 +80,13 @@ router.post('/:userId', authenticate, async function (req, res, next) {
try {
let mycart = await Cart.getCartByUserId(userId, idapp);
if (!order) {
return res.send({ code: server_constants.RIS_CODE_OK, cart: null });
}
// const myorder = Order.getOrderByID(order._id);
if (!addqty && !subqty && order) {
order._id = await Order.createOrder(order);
order._id = await Order.createOrder(order, mycart.codice_sconto);
if (!order._id) {
return res.send({ code: server_constants.RIS_CODE_ERR, cart: 0 });
}
@@ -78,15 +97,14 @@ router.post('/:userId', authenticate, async function (req, res, next) {
// no cart save empty cart to database then return response
let nuovo = false;
if (!mycart) {
let oldCart = new CartClass(order)
let oldCart = new CartClass(order);
cart = await Cart.createCart(oldCart.generateModel());
mycart = await Cart.getCartByUserId(userId, idapp);
nuovo = true;
}
let newCart = CartClass.constructByCart(mycart);
let newCart = await CartClass.constructByCart(mycart);
// order = await Product.updateProductInOrder(order);
if (!nuovo) {
// Controlla se sto inserendo un prodotto con 2 Negozi, non permetterlo !
@@ -101,35 +119,35 @@ router.post('/:userId', authenticate, async function (req, res, next) {
myord = arrord ? arrord[0] : null;
}
} else {
return res.send({ code: server_constants.RIS_CODE_ERR, cart: null, myord: null, msgerr: 'Non è possibile acquistare nello stesso ordine, su negozi differenti!' });
return res.send({
code: server_constants.RIS_CODE_ERR,
cart: null,
myord: null,
msgerr: 'Non è possibile acquistare nello stesso ordine, su negozi differenti!',
});
}
} else {
newCart.updatecarttotals(true);
await newCart.updatecarttotals(true);
await newCart.updateExtraOrder();
const arrord = await Order.getTotalOrderById(order._id);
myord = arrord ? arrord[0] : null;
}
cart = await Cart.updateCartByCartId(mycart._id, newCart.generateModel());
if (cart) {
const carttot = await Cart.getCartByUserId(userId, idapp);
if (order.idProduct)
product = await Product.getProductById(order.idProduct);
else if (order.product)
product = await Product.getProductById(order.product._id);
if (order.idProduct) product = await Product.getProductById(order.idProduct);
else if (order.product) product = await Product.getProductById(order.product._id);
return res.send({ code: server_constants.RIS_CODE_OK, cart: carttot, myord, product });
} else {
console.error('Err:', err);
return res.send({ code: server_constants.RIS_CODE_ERR, cart: null, myord: null });
}
} catch (e) {
console.error('Err:', e);
return res.send({ code: server_constants.RIS_CODE_ERR, cart: 0 });
}
})
});
router.delete('/:userId', authenticate, async function (req, res) {
console.log('DELETE Item');
@@ -140,17 +158,16 @@ router.delete('/:userId', authenticate, async function (req, res) {
const mycart = await Cart.getCartByUserId(userId, idapp);
const ord = await Order.findOne({ _id: orderId });
let idProduct = ''
let idProduct = '';
let product = null;
if (ord)
idProduct = ord.idProduct;
if (ord) idProduct = ord.idProduct;
// Rimuovere l'Ordine
const recremoved = await Order.deleteOne({ _id: orderId });
if (recremoved) {
// Rimuovere l'id sul Carrello
let newCart = CartClass.constructByCart(mycart);
let newCart = await CartClass.constructByCart(mycart);
await newCart.removeItem(orderId);
let carttot = null;
const cart = await Cart.updateCartByCartId(mycart._id, newCart.generateModel());
@@ -161,29 +178,27 @@ router.delete('/:userId', authenticate, async function (req, res) {
product = await Product.getProductById(idProduct);
}
console.log('carttot', carttot)
console.log('carttot', carttot);
return res.send({ code: server_constants.RIS_CODE_OK, cart: carttot, product });
}
return res.send({ code: server_constants.RIS_CODE_ERR, cart: null });
});
//PUT cart
router.put('/:userId', authenticate, async function (req, res, next) {
let userId = req.params.userId
let requestProduct = req.body
let { productId, color, size } = requestProduct.product
let userId = req.params.userId;
let requestProduct = req.body;
let { productId, color, size } = requestProduct.product;
try {
try {
const cart = await Cart.getCartByUserId(userId);
try {
const myprod = await Product.getProductByID(productId);
let newCart = oldCart.add(myprod, productId, { color, size })
let newCart = oldCart.add(myprod, productId, { color, size });
//exist cart in databse
if (cart.length > 0) {
@@ -193,7 +208,8 @@ router.put('/:userId', authenticate, async function (req, res, next) {
totalQty: newCart.totalQty,
totalPrice: newCart.totalPrice,
totalPriceCalc: newCart.totalPriceCalc,
userId: userId
totalPriceIntero: newCart.totalPriceIntero,
userId: userId,
});
res.json(result);
} catch (err) {
@@ -206,16 +222,16 @@ router.put('/:userId', authenticate, async function (req, res, next) {
totalQty: newCart.totalQty,
totalPrice: newCart.totalPrice,
totalPriceCalc: newCart.totalPriceCalc,
userId: userId
}
totalPriceIntero: newCart.totalPriceIntero,
userId: userId,
};
try {
const resultCart = await Cart.createCart(newCartobj);
} catch (err) {
return next(err)
return next(err);
}
res.status(201).json(resultCart);
}
} catch (err) {
return next(err);
}
@@ -223,32 +239,138 @@ router.put('/:userId', authenticate, async function (req, res, next) {
const product = await Product.getProductById(productId);
return res.send({ code: server_constants.RIS_CODE_OK, product });
} catch (err) {
return next(err)
return next(err);
}
let oldCart = new CartClass(c || {})
let oldCart = new CartClass(c || {});
} catch (e) {
return res.send({ code: server_constants.RIS_CODE_ERR, status: 0 });
}
});
})
//POST cart
router.post('/:userId/createorderscart', authenticate, async function (req, res, next) {
router.post('/:userId/app_sc', authenticate, async function (req, res, next) {
let idapp = req.body.idapp;
let cart_id = req.body.cart_id;
let userId = req.params.userId;
let status = req.body.status;
let note = req.body.note;
let codice_sconto = req.body.code;
let options = req.body.options;
try {
let mycart = await Cart.findOne({ _id: cart_id }).lean();
let mycart = null;
let valido = false;
let errmsg = '';
let recscontisticaTrovata = null;
try {
let mycart = await Cart.getCartCompletoByCartId(cart_id, idapp);
// let mycart = await Cart.findOne({ _id: cart_id }).lean();
if (codice_sconto === 'RIMUOVI') {
mycart = await Cart.findOneAndUpdate({ _id: cart_id }, { $set: { codice_sconto: '' } }, { new: true }).lean();
mycart = await aggiornaCarrello(mycart, userId, idapp);
return res.send({ mycart, valido, msg: 'Codice Sconto rimosso', rimuovi: true });
}
// attendi 3 secondi prima di poter inviare una nuova richiesta
await tools.attendiNSecondi(1);
if (codice_sconto) {
const recscontisticheTrovate = await CartClass.getRecSconto(idapp, codice_sconto, true);
if (recscontisticheTrovate && recscontisticheTrovate.length > 0) {
recscontisticaTrovata = recscontisticheTrovate[0];
}
if (recscontisticaTrovata) {
if (mycart.codice_sconto !== codice_sconto) {
mycart.codice_sconto = codice_sconto;
mycart.descr_sconto = recscontisticaTrovata.description;
await Cart.updateOne({ _id: cart_id }, { $set: { codice_sconto, descr_sconto: mycart.descr_sconto } });
}
valido = true;
mycart = await aggiornaCarrello(mycart, userId, idapp);
} else {
errmsg = `Codice sconto "${codice_sconto}" non valido oppure scaduto`;
}
}
return res.send({ mycart, valido, errmsg, recsconto: recscontisticaTrovata });
} catch (e) {
console.error('Err Applica Sconto', e);
return res.send({ valido: false, mycart: null, errmsg: e.message });
}
});
// Recupera il carrello
async function getCartById(cart_id) {
const cart = await Cart.findOne({ _id: cart_id }).lean();
return cart;
}
// Crea o aggiorna un ordine partendo dal cart
async function createOrUpdateOrderFromCart({ idapp, cart, userId, status, note }) {
let numorder = await OrdersCart.getLastNumOrder(idapp);
let numord_pers = await OrdersCart.getLastNumOrdPers(userId, idapp);
let myorderCart = await OrdersCart.getRecCartByUserId(userId, idapp, numorder);
if (!myorderCart) {
numorder++;
numord_pers++;
myorderCart = new OrdersCart({
idapp,
items: cart.items,
totalQty: cart.totalQty,
totalPrice: cart.totalPrice,
totalPriceCalc: cart.totalPriceCalc,
totalPriceIntero: cart.totalPriceIntero,
note_ordine_gas: cart.note_ordine_gas,
userId,
status,
note,
codice_sconto: cart.codice_sconto,
descr_sconto: cart.descr_sconto,
numorder,
numord_pers,
created_at: new Date(),
modify_at: new Date(),
});
}
return myorderCart;
}
// Gestisce l'invio ordine (checkout)
async function handleCheckout({ myorderCart, mycart, userId, idapp, req, options, userDest }) {
try {
const ris = await OrdersCart.updateOrdersCartById(-1, myorderCart);
await Order.updateStatusOrders(mycart.items, shared_consts.OrderStatus.CHECKOUT_SENT);
await Cart.deleteCartByCartId(mycart._id);
const orders = await OrdersCart.getOrdersCartByUserId(userId, idapp, myorderCart.numorder);
if (orders?.[0]) {
await OrdersCart.updateCmd(orders[0], shared_consts.OrderStatus.CHECKOUT_SENT, true, req, options);
await sendemail.sendEmail_OrderProduct(userDest.lang, idapp, orders[0], userDest);
const updatedOrder = await OrdersCart.findById(myorderCart._id).lean();
return { status: ris.status, orders, recOrderCart: updatedOrder };
}
} catch (err) {
console.error('Errore durante il checkout:', err);
throw err;
}
}
//POST cart
router.post('/:userId/createorderscart', authenticate, async function (req, res) {
try {
const { idapp, cart_id, status, note, options } = req.body;
const userId = req.params.userId;
// console.log('createorderscart', cart_id);
const mycart = await getCartById(cart_id);
if (!mycart) {
return res.send({
code: server_constants.RIS_CODE_OK,
@@ -257,93 +379,45 @@ router.post('/:userId/createorderscart', authenticate, async function (req, res,
});
}
let numorder = await OrdersCart.getLastNumOrder(idapp);
let numord_pers = await OrdersCart.getLastNumOrdPers(userId, idapp);
// Esiste l'ordine ?
let myorderCart = await OrdersCart.getRecCartByUserId(userId, idapp, numorder);
if (!myorderCart) {
// crea il nuovo numero d'ordine
numorder++;
numord_pers++;
// SE non esiste allora lo creo !
myorderCart = new OrdersCart({
idapp,
items: mycart.items,
totalQty: mycart.totalQty,
totalPrice: mycart.totalPrice,
totalPriceCalc: mycart.totalPriceCalc,
note_ordine_gas: mycart.note_ordine_gas,
userId,
status,
note,
numorder,
numord_pers,
created_at: new Date(),
modify_at: new Date(),
})
}
statusOrderCart = myorderCart.status;
const idordercart = myorderCart._id;
let myorderCart = await createOrUpdateOrderFromCart({ idapp, cart: mycart, userId, status, note });
let statusOrderCart = myorderCart.status;
const userDest = await User.findById(userId).lean();
if (!!mycart) {
if (status === shared_consts.OrderStatus.CHECKOUT_SENT) {
try {
const ris = await OrdersCart.updateOrdersCartById(-1, myorderCart);
// Gestisci il risultato qui
await Order.updateStatusOrders(mycart.items, status);
const checkoutResult = await handleCheckout({
myorderCart,
mycart,
userId,
idapp,
req,
options,
userDest,
});
const myris = ris;
// Cancella il Cart appena salvato in OrdersCart
return Cart.deleteCartByCartId(mycart._id)
.then((ris) => {
return OrdersCart.getOrdersCartByUserId(userId, idapp, numorder)
.then(async (orders) => {
if (!!orders) {
if (orders[0]) {
await OrdersCart.updateCmd(orders[0], status, true, req, options);
// Invia la email dell'Ordine
sendemail.sendEmail_OrderProduct(userDest.lang, idapp, orders[0], userDest)
.then(async (ris) => {
myorderCart = await OrdersCart.findById(idordercart).lean();
return res.send({
code: server_constants.RIS_CODE_OK,
status: myris.status,
orders: orders,
recOrderCart: myorderCart
status: checkoutResult.status,
orders: checkoutResult.orders,
recOrderCart: checkoutResult.recOrderCart,
});
});
}
}
});
})
} catch (err) {
console.error("Errore durante l'aggiornamento dell'ordine:", err);
return res.send({ code: server_constants.RIS_CODE_ERR, status: 0 });
}
}
}
// console.log('SEND OK', statusOrderCart);
return res.send({
code: server_constants.RIS_CODE_OK,
status: statusOrderCart,
recOrderCart: myorderCart
recOrderCart: myorderCart,
});
} catch (e) {
console.error('Err', e);
console.error('Errore generale:', e);
return res.send({ code: server_constants.RIS_CODE_ERR, status: 0, recOrderCart: null });
}
});
//POST cart
@@ -356,22 +430,19 @@ router.post('/:userId/ordercartstatus', authenticate, async function (req, res,
const { User } = require('../models/user');
let myOrdersCart = await OrdersCart.findOne({ idapp, _id: order_id }).lean();
if ((userId !== String(req.user._id)) && !User.isManager(req.user.perm)) {
if (userId !== String(req.user._id) && !User.isManager(req.user.perm)) {
// I'm trying to write something not mine!
return res.status(404).send({ code: server_constants.RIS_CODE_TODO_CREATING_NOTMYUSER });
}
try {
if (!!myOrdersCart) {
let fields_to_update = { status };
await OrdersCart.findOneAndUpdate({ _id: order_id }, { $set: fields_to_update }
, { new: false })
.then(async (ris) => {
await OrdersCart.findOneAndUpdate({ _id: order_id }, { $set: fields_to_update }, { new: false }).then(
async (ris) => {
const userDest = await User.findById(myOrdersCart.userId).lean();
if (ris) {
@@ -390,15 +461,14 @@ router.post('/:userId/ordercartstatus', authenticate, async function (req, res,
}
if (ordertype !== '') {
sendemail.sendEmail_Order(userDest.lang, idapp, myOrdersCart, userDest, ordertype, status)
.then((ris) => {
})
sendemail
.sendEmail_Order(userDest.lang, idapp, myOrdersCart, userDest, ordertype, status)
.then((ris) => {});
}
}
}
})
}
);
let orderscart = null;
@@ -410,14 +480,11 @@ router.post('/:userId/ordercartstatus', authenticate, async function (req, res,
}
return res.send({ code: server_constants.RIS_CODE_OK, status, orders: orderscart });
}
} catch (e) {
console.error('err', e);
return res.send({ code: server_constants.RIS_CODE_ERR, status: 0 });
}
});
//POST cart
@@ -428,23 +495,21 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
const { User } = require('../models/user');
try {
let queryord = [];
let queryord = []
let filtroOrdini = []
let filtroOrdini = [];
if (idGasordine) {
const gasordine = {
$match: {
idGasordine: {
$type: "objectId", // Checks if the field is of type ObjectId
$eq: new ObjectId(idGasordine) // Compares the value to a specific ObjectId
$type: 'objectId', // Checks if the field is of type ObjectId
$eq: new ObjectId(idGasordine), // Compares the value to a specific ObjectId
},
},
};
queryord.push(gasordine);
}
}
}
queryord.push(gasordine)
}
const query = [
{
@@ -506,15 +571,15 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
},
{
$lookup: {
from: "orderscarts",
localField: "_id",
foreignField: "items.order",
as: "matchingOrders",
from: 'orderscarts',
localField: '_id',
foreignField: 'items.order',
as: 'matchingOrders',
},
},
{
$match: {
"matchingOrders": {
matchingOrders: {
$ne: [],
},
},
@@ -539,10 +604,7 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
},
totalQuantity: {
$sum: {
$add: [
'$quantity',
'$quantitypreordered',
],
$add: ['$quantity', '$quantitypreordered'],
},
},
totalPrice_acquistato: {
@@ -550,10 +612,7 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
$multiply: [
'$product.price_acquistato',
{
$add: [
'$quantity',
'$quantitypreordered',
],
$add: ['$quantity', '$quantitypreordered'],
},
],
},
@@ -563,10 +622,7 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
$multiply: [
'$product.price',
{
$add: [
'$quantity',
'$quantitypreordered',
],
$add: ['$quantity', '$quantitypreordered'],
},
],
},
@@ -580,25 +636,22 @@ router.post('/:userId/gestord', authenticate, async function (req, res, next) {
$sort: {
name: 1,
},
}
]
},
];
queryord = [...queryord, ...query]
queryord = [...queryord, ...query];
filtroOrdini = queryord;
const arrout = await Order.aggregate(filtroOrdini);
for (const rec of arrout) {
}
return res.send({ code: server_constants.RIS_CODE_OK, arrout });
} catch (e) {
console.error('Err', e);
}
});
module.exports = router;

View File

@@ -0,0 +1,69 @@
const express = require('express');
const router = express.Router();
const tools = require('../tools/general');
var server_constants = require('../tools/server_constants');
var { Project } = require('../models/project');
const { User } = require('../models/user');
var { authenticate, auth_default } = require('../middleware/authenticate');
const _ = require('lodash');
const { Catalog } = require('../models/catalog');
const globalTables = require('../tools/globalTables');
router.post('/', auth_default, async function (req, res, next) {
const idapp = req.body.idapp;
const userId = req.body.userId;
let ismanager = await tools.isManagerByReq(req);
let catalogs = await Catalog.findAllIdApp(idapp);
let orders = null;
if (catalogs) return res.send({ code: server_constants.RIS_CODE_OK, catalogs, orders });
else return res.status(400).send({ code: server_constants.RIS_CODE_OK, catalogs, orders });
});
router.get('/id/:id', async function (req, res) {
const id = req.params.id;
try {
var catalog = await Catalog.getCatalogById(id);
if (catalog) {
return res.send({ code: server_constants.RIS_CODE_OK, catalog: catalog });
} else {
return res.send({ code: server_constants.RIS_CODE_OK, catalog: null });
}
} catch (e) {
console.error('Error fetching catalog by ID:', e);
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message });
}
});
router.post('/addnew', authenticate, async function (req, res, next) {
const idapp = req.body.idapp;
const data = req.body.newCatalog;
const username = req.user.username;
try {
const newrecs = await globalTables.addNewCatalog(idapp, data, username);
if (newrecs) {
return res.send({ code: server_constants.RIS_CODE_OK, data: newrecs });
} else {
return res.send({ code: server_constants.RIS_CODE_OK, data: null });
}
} catch (e) {
console.error('Error fetching catalog by ID:', e);
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message });
}
});
module.exports = router;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,57 @@
const express = require('express');
const router = express.Router();
const tools = require('../tools/general');
var server_constants = require('../tools/server_constants');
const { User } = require('../models/user');
var { authenticate, auth_default } = require('../middleware/authenticate');
const _ = require('lodash');
const { MyScrapingBook } = require('../models/myscrapingbook');
const Product = require('../models/product');
const AmazonBookScraper = require('../modules/Scraping');
//GET /products
router.post('/', auth_default, async function (req, res, next) {
const idapp = req.body.idapp;
const isbn = req.body.isbn;
const forzacaricamento = req.body.forzacaricamento;
try {
let myscraping = null;
if (isbn) {
myscraping = await MyScrapingBook.findOne({ isbn }).lean();
if (!myscraping && forzacaricamento) {
const scraper = new AmazonBookScraper();
const options = {
update: false,
forzaricarica: false,
};
const myproduct = await Product.getProductByIsbn(idapp, isbn);
if (myproduct && myproduct.length > 0) {
myscraping = await scraper.scrapeISBN(myproduct[0], isbn, options);
// console.log(myscraping);
}
}
}
if (myscraping) {
return res.send({ code: server_constants.RIS_CODE_OK, myscraping });
} else {
return res.send({ code: server_constants.RIS_CODE_OK, myscraping: null });
}
} catch (e) {
console.error(e);
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: e.message });
}
});
module.exports = router;

View File

@@ -114,7 +114,7 @@ router.post('/', async (req, res) => {
user.surname = user.surname.trim();
if ((user.aportador_solidario === 'tuo_username') || (user.aportador_solidario === '{username}')) {
user.aportador_solidario = 'paoloar77';
user.aportador_solidario = 'surya1977';
}
// tools.mylog("LANG PASSATO = " + user.lang, "IDAPP", user.idapp);
@@ -393,7 +393,7 @@ router.post('/', async (req, res) => {
res.status(400).send(e);
});
} catch (e) {
console.error(e.message);
console.error('Error: /users REG: ' + e.message);
}
});
@@ -1173,7 +1173,7 @@ router.post('/dbop', authenticate, async (req, res) => {
idapp = req.body.idapp;
locale = req.body.locale;
if (!User.isAdmin(req.user.perm)) {
if (!User.isCollaboratore(req.user.perm)) {
return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED });
}

View File

@@ -42,19 +42,19 @@ function checkifSendEmail() {
}
module.exports = {
sendEmail_base_e_manager: function (idapp, template, to, mylocalsconf, replyTo, transport, previewonly) {
this.sendEmail_base(template, to, mylocalsconf, replyTo, transport, previewonly);
sendEmail_base_e_manager: async function (idapp, template, to, mylocalsconf, replyTo, transport, previewonly) {
await this.sendEmail_base(template, to, mylocalsconf, replyTo, transport, previewonly);
this.sendEmail_base(template, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '', transport, previewonly);
await this.sendEmail_base(template, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '', transport, previewonly);
if (tools.isManagAndAdminDifferent(idapp)) {
const email = tools.getManagerEmailByIdApp(idapp);
this.sendEmail_base(template, email, mylocalsconf, '', transport, previewonly);
await this.sendEmail_base(template, email, mylocalsconf, '', transport, previewonly);
}
},
sendEmail_base: function (template, to, mylocalsconf, replyTo, transport, previewonly) {
sendEmail_base: async function (template, to, mylocalsconf, replyTo, transport, previewonly) {
if (to === '')
return false;
@@ -106,6 +106,15 @@ module.exports = {
}*/
}
// se non è presente la password, non inviare l'email e manda messaggio di errore !
if (!paramemail.transport.options.auth.pass) {
let email = paramemail.transport.options.auth.user;
console.error('❌ Password mancante ! Impossibile inviare le email. user=', email);
return false;
}
// console.table(paramemail.transport);
// console.log('2 . paramemail.transport', paramemail.transport);
@@ -125,9 +134,13 @@ module.exports = {
},
locals: mylocalsconf,
}).then((ris) => {
if (ris?.response && ris.response.includes('Ok')) {
console.log('✅ Email INVIATA')
}
// console.log('ris EMAIL', ris);
return !!ris;
}).catch((err) => {
console.log('❌ Email NON INVIATA!');
console.error('sendEmail_base Error: ', err);
return false;
});
@@ -199,10 +212,10 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(user, mylocalsconf);
this.sendEmail_base(tools.getpathregByIdApp(idapp, lang), emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
await this.sendEmail_base(tools.getpathregByIdApp(idapp, lang), emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
// Send to the Admin an Email
this.sendEmail_base('admin/registration/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/registration/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await telegrambot.notifyToTelegram(telegrambot.phase.REGISTRATION, mylocalsconf);
@@ -242,17 +255,17 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(iscritto, mylocalsconf);
this.sendEmail_base('iscrizione_conacreis/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
await this.sendEmail_base('iscrizione_conacreis/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
// Send to the Admin an Email
this.sendEmail_base('admin/iscrizione_conacreis/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/iscrizione_conacreis/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await telegrambot.notifyIscrizioneToTelegram(telegrambot.phase.ISCRIZIONE_CONACREIS, mylocalsconf, 'MSG_ISCRITTO_CONACREIS');
tools.sendNotifToAdmin(idapp, true, 'Iscrizione Conacreis : ' + mylocalsconf.name + ' ' + mylocalsconf.surname + ' (' + mylocalsconf.username + ')');
if (tools.isManagAndAdminDifferent(idapp)) {
this.sendEmail_base('admin/iscrizione_conacreis/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/iscrizione_conacreis/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
}
},
@@ -275,17 +288,17 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(iscritto, mylocalsconf);
this.sendEmail_base('iscrizione_arcadei/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
await this.sendEmail_base('iscrizione_arcadei/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
// Send to the Admin an Email
this.sendEmail_base('admin/iscrizione_arcadei/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/iscrizione_arcadei/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await telegrambot.notifyIscrizioneToTelegram(telegrambot.phase.ISCRIZIONE_ARCADEI, mylocalsconf, 'MSG_ISCRITTO_ARCADEI');
tools.sendNotifToAdmin(idapp, true, 'Iscrizione Arcadei : ' + mylocalsconf.name + ' ' + mylocalsconf.surname + ' (' + mylocalsconf.username + ')');
if (tools.isManagAndAdminDifferent(idapp)) {
this.sendEmail_base('admin/iscrizione_arcadei/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/iscrizione_arcadei/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
}
} catch (e) {
console.error('Err', e);
@@ -307,7 +320,7 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(user, mylocalsconf);
this.sendEmail_base('resetpwd/' + lang, emailto, mylocalsconf, '');
await this.sendEmail_base('resetpwd/' + lang, emailto, mylocalsconf, '');
},
sendEmail_RisRicevuti: async function (lang, userDest, emailto, idapp, myrec) {
@@ -332,7 +345,7 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(userDest, mylocalsconf);
this.sendEmail_base('risricevuti/' + lang, emailto, mylocalsconf, '');
await this.sendEmail_base('risricevuti/' + lang, emailto, mylocalsconf, '');
},
sendEmail_Booking: async function (res, lang, emailto, user, idapp, recbooking) {
@@ -370,13 +383,13 @@ module.exports = {
texthtml = 'makebooking';
}
this.sendEmail_base('booking/' + texthtml + '/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
await this.sendEmail_base('booking/' + texthtml + '/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
// Send Email also to the Admin
this.sendEmail_base('admin/' + texthtml + '/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/' + texthtml + '/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
if (tools.isManagAndAdminDifferent(idapp)) {
this.sendEmail_base('admin/' + texthtml + '/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/' + texthtml + '/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
}
});
@@ -459,13 +472,13 @@ module.exports = {
telegrambot.sendMsgTelegramToTheManagers(idapp, msgtelegram);
this.sendEmail_base('booking/cancelbooking/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
await this.sendEmail_base('booking/cancelbooking/' + lang, emailto, mylocalsconf, tools.getreplyToEmailByIdApp(idapp));
// Send Email also to the Admin
this.sendEmail_base('admin/cancelbooking/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/cancelbooking/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
if (tools.isManagAndAdminDifferent(idapp)) {
this.sendEmail_base('admin/cancelbooking/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/cancelbooking/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
}
},
@@ -607,10 +620,10 @@ module.exports = {
if (sendnews) {
// Send to the Admin an Email
this.sendEmail_base('admin/added_to_newsletter/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/added_to_newsletter/' + tools.LANGADMIN, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
if (tools.isManagAndAdminDifferent(idapp)) {
this.sendEmail_base('admin/added_to_newsletter/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
await this.sendEmail_base('admin/added_to_newsletter/' + tools.LANGADMIN, tools.getManagerEmailByIdApp(idapp), mylocalsconf, '');
}
}
@@ -754,7 +767,7 @@ module.exports = {
},
getTransport: (mylocalsconf) => {
console.log('getTransport');
// console.log('getTransport');
// Create Transport
let smtpTransport = null;
@@ -845,7 +858,7 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(user, mylocalsconf);
this.sendEmail_base_e_manager(idapp, 'ecommerce/makeorder/' + lang, mylocalsconf.emailto, mylocalsconf,
await this.sendEmail_base_e_manager(idapp, 'ecommerce/makeorder/' + lang, mylocalsconf.emailto, mylocalsconf,
mylocalsconf.dataemail.email_reply);
} else {
console.log('Invio Email non eseguito perchè sei in TEST !');
@@ -881,7 +894,7 @@ module.exports = {
mylocalsconf = this.setParamsForTemplate(user, mylocalsconf);
if ((status !== shared_consts.OrderStatus.CANCELED) && (status !== shared_consts.OrderStatus.COMPLETED)) {
const esito = this.sendEmail_base('ecommerce/' + ordertype + '/' + lang, mylocalsconf.emailto, mylocalsconf,
const esito = await this.sendEmail_base('ecommerce/' + ordertype + '/' + lang, mylocalsconf.emailto, mylocalsconf,
mylocalsconf.dataemail.email_reply);
// this.sendEmail_base('ecommerce/' + ordertype + '/' + lang, tools.getAdminEmailByIdApp(idapp), mylocalsconf, '');
@@ -980,7 +993,7 @@ module.exports = {
// Send Email to the User
// console.log('-> Invio Email (', mynewsrec.numemail_sent, '/', mynewsrec.numemail_tot, ')');
const esito = this.sendEmail_base('newsletter/' + lang, mylocalsconf.emailto, mylocalsconf,
const esito = await this.sendEmail_base('newsletter/' + lang, mylocalsconf.emailto, mylocalsconf,
mylocalsconf.dataemail.email_reply, smtpTransport);
if ((mynewsrec.numemail_sent % 100) === 0) {

View File

@@ -13,7 +13,7 @@ const _ = require('lodash');
const cors = require('cors');
// console.log(" 2) fs");
const fs = require('fs');
const fs = require('fs'); // 👈 Usa il modulo promises
var https = require('https');
var http = require('http');
@@ -128,6 +128,8 @@ connectToDatabase(connectionUrl, options)
const site_router = require('./router/site_router');
const admin_router = require('./router/admin_router');
const products_router = require('./router/products_router');
const myscraping_router = require('./router/myscraping_router');
const catalogs_router = require('./router/catalogs_router');
const cart_router = require('./router/cart_router');
const orders_router = require('./router/orders_router');
const city_router = require('./router/city_router');
@@ -136,6 +138,7 @@ connectToDatabase(connectionUrl, options)
const mygen_router = require('./router/mygen_router');
const aitools_router = require('./router/aitools_router');
const article_router = require('./router/articleRoutes');
const api_router = require('./router/api_router');
const { MyEvent } = require('./models/myevent');
@@ -203,7 +206,6 @@ connectToDatabase(connectionUrl, options)
// });
});
}
if (process.env.NODE_ENV === 'production') {
console.log('*** PRODUCTION! ');
}
@@ -237,6 +239,8 @@ connectToDatabase(connectionUrl, options)
app.use('/site', site_router);
app.use('/admin', admin_router);
app.use('/products', products_router);
app.use('/myscraping', myscraping_router);
app.use('/catalogs', catalogs_router);
app.use('/cart', cart_router);
app.use('/orders', orders_router);
app.use('/city', city_router);
@@ -245,6 +249,7 @@ connectToDatabase(connectionUrl, options)
app.use('/mygen', mygen_router);
app.use('/aitools', aitools_router);
app.use('/apisqlsrv', article_router);
app.use('/api', api_router);
mystart();
});
@@ -262,13 +267,13 @@ connectToDatabase(connectionUrl, options)
await tools.getApps();
let miapass = '';
if (process.env.PROD !== 1) {
testmsgwebpush();
// tools.sendNotifToAdmin('Riparti', 'Riparti');
let miapass = '';
if (miapass !== '') {
let crypt = tools.cryptdata(miapass);
let decrypt = tools.decryptdata(crypt);
@@ -280,8 +285,24 @@ connectToDatabase(connectionUrl, options)
mycron();
}
miapass = 'PROVA123@';
let crypt = tools.cryptdata(miapass);
let decrypt = tools.decryptdata(crypt);
telegrambot = require('./telegram/telegrambot');
if (decrypt === miapass) {
console.log('✅ Decrypt OK');
// OK FUNZIONA
} else {
let msgerr = '❌ ERRORE! la decrittazione non funziona! ';
console.error(msgerr);
await telegrambot.sendMsgTelegramToTheAdminAllSites(
msgerr,
false
);
}
await inizia();
await resetProcessingJob();
@@ -531,16 +552,16 @@ connectToDatabase(connectionUrl, options)
try {
// console.log('checkdir', folderprof);
if (!fs.existsSync(folderprof)) {
if (!(await tools.isFileExistsAsync(folderprof))) {
console.log('*** Creadir', folderprof);
fs.mkdirSync(folderprof);
await fs.mkdirSync(folderprof);
}
folderprof = dir + 'profile/' + myuser.username + '/' + table;
// console.log('checkdir', folderprof);
if (!fs.existsSync(folderprof)) {
if (!(await tools.isFileExistsAsync(folderprof))) {
console.log('creadir', folderprof);
fs.mkdirSync(folderprof);
await fs.mkdirSync(folderprof);
}
} catch (e) {}
}
@@ -554,18 +575,18 @@ connectToDatabase(connectionUrl, options)
// console.log('file', file);
// console.log('filefrom', filefrom);
if (!tools.isFileExists(file)) {
if (!(await tools.isFileExistsAsync(file))) {
// non esiste
console.log('non esiste', file);
console.log(' filefrom', filefrom);
console.log(' filefrom2', filefrom2);
}
if (!tools.isFileExists(file) && tools.isFileExists(filefrom)) {
if (!(await tools.isFileExistsAsync(file)) && (await tools.isFileExistsAsync(filefrom))) {
console.log('@@@@@@ copia file:', filefrom, 'a', file);
tools.copy(filefrom, file);
}
if (!tools.isFileExists(file) && tools.isFileExists(filefrom2)) {
if (!(await tools.isFileExistsAsync(file)) && (await tools.isFileExistsAsync(filefrom2))) {
console.log('@@@@@@ copia file 2:', filefrom2, 'a', file);
tools.copy(filefrom2, file);
}
@@ -671,99 +692,112 @@ connectToDatabase(connectionUrl, options)
}
}
function getCredentials(hostname) {
// Funzione migliorata per ottenere chiave e certificato
async function getCredentials(hostname) {
try {
let keyPath, certPath;
if (NUOVO_METODO_TEST) {
if (METODO_MULTI_CORS) {
const fileprivkey = `/etc/letsencrypt/live/${hostname}/` + process.env.PATH_CERT_KEY;
const filecert = `/etc/letsencrypt/live/${hostname}/` + process.env.PATH_SERVER_CRT;
// Percorso basato su hostname (Let's Encrypt)
keyPath = `/etc/letsencrypt/live/${hostname}/${process.env.PATH_CERT_KEY}`;
certPath = `/etc/letsencrypt/live/${hostname}/${process.env.PATH_SERVER_CRT}`;
} else {
// Percorso relativo
keyPath = path.resolve(`./${process.env.PATH_CERT_KEY}`);
certPath = path.resolve(`./${process.env.PATH_SERVER_CRT}`);
}
console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert);
// Verifica esistenza file
if (!(await tools.isFileExistsAsync(keyPath))) {
throw new Error(`Chiave privata non trovata: ${keyPath}`);
}
if (!(await tools.isFileExistsAsync(certPath))) {
throw new Error(`Certificato non trovato: ${certPath}`);
}
/* return {
// Leggi chiave e certificato
const key = fs.readFileSync(keyPath, 'utf8');
const cert = fs.readFileSync(certPath, 'utf8');
SNICallback: function (hostname, callback) {
console.log('hostname: ', hostname);
if (domains.includes(hostname)) {
const fileprivkey = `/etc/letsencrypt/live/${hostname}/privkey.pem`;
const filecert = `/etc/letsencrypt/live/${hostname}/fullchain.pem`;
// console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert);
const domainCert = {
key: fs.readFileSync(fileprivkey, "utf8"),
cert: fs.readFileSync(filecert, "utf8"),
// Restituisci oggetto con credenziali + configurazione TLS avanzata
return {
key,
cert,
ciphers:
'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384',
honorCipherOrder: true,
secureOptions: require('constants').OPENSSL_OPTIONS_TLS_NODELAY,
secureProtocol: 'TLSv1_2_method', // Forza TLS 1.2+ (meglio se usi TLSv1_3)
};
callback(null, domainCert);
} else {
callback(null, { key: privateKey, cert: certificate });
// Metodo legacy (opzionale)
throw new Error('Metodo legacy non supportato');
}
}
};*/
try {
const key = fs.readFileSync(fileprivkey, 'utf8');
const cert = fs.readFileSync(filecert, 'utf8');
return { key, cert };
} catch (error) {
console.error(`Errore nel caricamento delle credenziali per ${hostname}:`, error);
// Gestisci l'errore, per esempio ritorna null o lancia un'eccezione
}
} else {
const keyStream = path.resolve(`./${process.env.PATH_CERT_KEY}`);
const certificateStream = path.resolve(`./${process.env.PATH_SERVER_CRT}`);
const privateKey = fs.readFileSync(keyStream, 'utf8');
const certificate = fs.readFileSync(certificateStream, 'utf8');
return { key: privateKey, cert: certificate };
console.error(`[getCredentials] Errore per ${hostname}:`, error.message);
throw error;
}
}
// Caso di default non specificato, potrebbe essere necessario aggiungere una gestione degli errori qui
// 🔧 Funzione factory per creare e configurare un server HTTPS
function createHttpsServer({ hostname, port, website, app, credentials, timeoutMinutes = 5 }) {
const server = https.createServer(credentials, app);
const timeoutMs = 1000 * 60 * timeoutMinutes;
// ⏱️ Timeout globale per la connessione TCP
server.setTimeout(timeoutMs, () => {
console.log(`TCP timeout su server: ${hostname}:${port}`);
});
// ⏱️ Timeout per singola richiesta HTTP
server.on('request', (req, res) => {
req.setTimeout(timeoutMs);
res.setTimeout(timeoutMs);
});
// 📡 Eventuali altri eventi utili
server.on('clientError', (err, socket) => {
console.error(`Client error su ${hostname}:${port}:`, err.message);
});
// Avvia il server
server.listen(port, () => {
console.log(
'⭐️⭐️⭐️⭐️⭐️ HTTPS server: %s Port: %d%s',
hostname,
port,
website ? ' WebSite = ' + website : ''
);
});
return server;
}
function startServer(app, port) {
try {
const isProduction = ['production', 'test'].includes(process.env.NODE_ENV);
function parseDomains() {
let domains = [];
let domains_allowed = [];
let domainsAllowed = [];
try {
if (process.env.DOMAINS) domains = JSON.parse(process.env.DOMAINS);
if (process.env.DOMAINS_ALLOWED) domains_allowed = JSON.parse(process.env.DOMAINS_ALLOWED);
if (process.env.DOMAINS_ALLOWED) domainsAllowed = JSON.parse(process.env.DOMAINS_ALLOWED);
} catch (error) {
console.error('Errore durante la conversione della stringa DOMAINS:', error);
console.error('Errore parsing DOMAINS:', error);
}
return { domains, domainsAllowed };
}
console.log('domains', domains);
let httpsServer = null;
let httpServer = null;
console.log('isProduction', isProduction);
const NOCORS = false;
const ISDEBUG = false;
let corsOptions = {};
if (NOCORS) {
console.log('NOCORS');
corsOptions = {
exposedHeaders: ['x-auth', 'x-refrtok'], // Intestazioni da esporre al client
};
} else {
console.log('WITH CORS');
let credentials = true;
let allowedOrigins = null;
function buildAllowedOrigins(domains, domainsAllowed, isProduction) {
if (!isProduction) {
allowedOrigins = 'https://localhost:3000';
} else {
allowedOrigins = domains.flatMap((domain) => [
return [
'https://localhost:3000',
'https://localhost:8089',
'https://localhost:8084',
'https://localhost:8088',
'https://localhost:8099',
];
}
const baseOrigins = domains.flatMap((domain) => [
`https://${domain.hostname}`,
`https://api.${domain.hostname}`,
`https://test.${domain.hostname}`,
@@ -774,49 +808,43 @@ connectToDatabase(connectionUrl, options)
`http://testapi.${domain.hostname}`,
]);
// Aggiungi i domini da DOMAINS_ALLOWED
allowedOrigins = allowedOrigins.concat(
domains_allowed.map((domain) => [`https://${domain}`, `http://${domain}`]).flat()
);
const allowedExtra = domainsAllowed.flatMap((domain) => [`https://${domain}`, `http://${domain}`]);
return [...baseOrigins, ...allowedExtra];
}
console.log('allowedOrigins', allowedOrigins);
let myorigin = '*';
if (domains.length > 0) {
myorigin = (origin, callback) => {
try {
// Validazione dell'input
if (origin === undefined) {
console.log('✅ Origin UNDEFINED... vado avanti lo stesso !');
return callback(null, true);
}
if (!origin || typeof origin !== 'string' || !/^https?:\/\/[^\s/$.?#].[^\s]*$/.test(origin)) {
console.error('❌ Origine non valida:', origin);
return callback(new Error('Origine non valida'), false);
}
// Controllo delle origini consentite
if (allowedOrigins.includes(origin)) {
// console.log('✅ Origine consentita:', origin);
return callback(null, true);
}
// Blocco delle origini non autorizzate
console.warn('❌ Origine bloccata:', origin);
return callback(new Error('CORS non permesso per questa origine'), false);
} catch (error) {
console.error("Errore durante la verifica dell'origine:", error.message);
return callback(error, false);
}
function createCorsOptions(domains, domainsAllowed, isProduction, noCors = false) {
if (noCors) {
console.log('NOCORS mode enabled');
return {
exposedHeaders: ['x-auth', 'x-refrtok'],
};
}
// Configurazione CORS dettagliata
const corsOptions = {
origin: myorigin,
credentials,
const allowedOrigins = buildAllowedOrigins(domains, domainsAllowed, isProduction);
const originValidator = (origin, callback) => {
if (!origin) {
// console.log('✅ Origin undefined or empty — allowing');
return callback(null, true);
}
if (typeof origin !== 'string' || !/^https?:\/\/[^\s/$.?#].[^\s]*$/.test(origin)) {
console.error('❌ Invalid origin:', origin);
return callback(new Error('Origine non valida'), false);
}
if (allowedOrigins.includes(origin)) {
return callback(null, true);
}
console.warn('❌ Origin blocked:', origin);
return callback(new Error('CORS non permesso per questa origine'), false);
};
return {
origin: originValidator,
credentials: true,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
allowedHeaders: [
'Origin',
@@ -828,52 +856,32 @@ connectToDatabase(connectionUrl, options)
'x-refrtok',
],
exposedHeaders: ['x-auth', 'x-refrtok'],
maxAge: 86400, // Preflight cache 24 ore
maxAge: 86400,
preflightContinue: false,
optionsSuccessStatus: 204,
};
// Applica CORS come primo middleware
app.use(cors(corsOptions));
// HO AGGIUNTO QUESTA RIGA PER IL CORS !!!!!!!
app.use(express.json()); // Middleware per il parsing del corpo JSON
app.options('*', cors(corsOptions)); // Gestisce tutte le richieste OPTIONS
// Middleware personalizzato per assicurare gli headers CORS
/*app.use((req, res, next) => {
const origin = req.headers.origin || '*';
if (allowedOrigins.includes(origin) || corsOptions.origin === '*') {
// console.log(' ... ORIGIN', origin);
res.setHeader('Access-Control-Allow-Origin', origin);
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
res.setHeader('Access-Control-Allow-Credentials', 'true');
res.setHeader('Access-Control-Expose-Headers', 'x-auth, x-refrtok');
}
next();
});*/
// Log middleware per debug
function setupMiddleware(app, corsOptions, isDebug = false) {
app.use(cors(corsOptions));
app.use(express.json());
app.options('*', cors(corsOptions));
if (isDebug) {
app.use((req, res, next) => {
if (ISDEBUG) {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
console.log('Request Headers:', req.headers);
}
// Intercetta la risposta per loggare gli headers
const oldSend = res.send;
res.send = function (...args) {
if (ISDEBUG) {
console.log('Response Headers:', res.getHeaders());
}
return oldSend.apply(res, args);
};
next();
});
}
// Gestione errori CORS
app.use((err, req, res, next) => {
if (err.message === 'CORS non permesso per questa origine') {
console.error('❌ Errore CORS:', {
@@ -881,106 +889,89 @@ connectToDatabase(connectionUrl, options)
method: req.method,
path: req.path,
});
res.status(403).json({
error: '❌ CORS non permesso per questa origine (' + req.headers.origin + ')',
return res.status(403).json({
error: `❌ CORS non permesso per questa origine (${req.headers.origin})`,
origin: req.headers.origin,
});
} else {
next(err);
}
next(err);
});
}
async function createHttpOrHttpsServer(app, port, isProduction, domains) {
if (isProduction) {
for (let i = 0; i < domains.length; i++) {
const mycredentials = getCredentials(domains[i].hostname);
// console.log('credentials: ', credentials);
httpsServer = https.createServer(mycredentials, app);
console.log(
'⭐️⭐️⭐️⭐️⭐️ HTTPS server: ' + domains[i].hostname + ' Port:',
domains[i].port + (domains[i].website ? 'WebSite = ' + domains[i].website : '')
);
httpsServer.listen(domains[i].port);
const promises = domains.map(async (domain) => {
const credentials = await getCredentials(domain.hostname);
return createHttpsServer({
hostname: domain.hostname,
port: domain.port,
website: domain.website,
app,
credentials,
timeoutMinutes: 6,
});
});
await Promise.all(promises);
return null;
}
} else {
if (process.env.HTTPS_LOCALHOST === 'true') {
let mycredentials = null;
try {
const keyStream = path.resolve(`./${process.env.PATH_CERT_KEY}`);
const certificateStream = path.resolve(`./${process.env.PATH_SERVER_CRT}`);
const key = fs.readFileSync(path.resolve(`./${process.env.PATH_CERT_KEY}`), 'utf8');
const cert = fs.readFileSync(path.resolve(`./${process.env.PATH_SERVER_CRT}`), 'utf8');
const privateKey = fs.readFileSync(keyStream, 'utf8');
const certificate = fs.readFileSync(certificateStream, 'utf8');
mycredentials = {
key: privateKey,
cert: certificate,
const credentials = {
key,
cert,
ciphers:
'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES256-SHA384',
honorCipherOrder: true,
secureProtocol: 'TLSv1_2_method',
};
} catch (error) {
console.error('Errore durante la lettura dei file di certificazione, error:', error.message);
throw error;
}
if (mycredentials) {
httpsServer = https.createServer(mycredentials, app);
console.log('⭐️⭐️⭐️ HTTPS server IN LOCALE : port', port);
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(port);
} else {
httpServer = http.createServer(app);
if (httpServer) {
console.log('⭐️⭐️⭐️ HTTP server IN LOCALE : port', port);
console.log('⭐️ HTTPS server running locally on port', port);
return httpsServer;
} catch (error) {
console.error('Errore caricamento certificati HTTPS locali:', error.message);
// fallback HTTP server
}
}
const httpServer = http.createServer(app);
httpServer.listen(port);
}
console.log('⭐️ HTTP server running on port', port);
return httpServer;
}
// console.log('credentials', credentials);
} else {
httpServer = http.createServer(app);
if (httpServer) {
console.log('⭐️⭐️⭐️ HTTP server IN LOCALE : port', port);
httpServer.listen(port);
}
}
function setupWebSocketServer(httpOrHttpsServer) {
if (!httpOrHttpsServer) {
console.error('Nessun server HTTP o HTTPS disponibile per WebSocket');
return null;
}
let wss = null;
const wss = new WebSocket.Server({ server: httpOrHttpsServer });
if (httpsServer) {
wss = new WebSocket.Server({ server: httpsServer });
} else if (httpServer) {
wss = new WebSocket.Server({ server: httpServer });
} else {
// console.error('Nessun server HTTP o HTTPS disponibile per WebSocket');
// process.exit(1);
}
if (wss) {
wss.on('connection', (ws) => {
console.log('Client socket connected...');
const { User } = require('./models/user');
const pty = require('node-pty');
let scriptProcess = null;
const pty = require('node-pty');
ws.on('message', (message) => {
const parsedMessage = JSON.parse(message);
ws.on('message', async (message) => {
try {
if (parsedMessage.type === 'start_script' && User.isAdminById(parsedMessage.user_id)) {
if (scriptProcess) {
scriptProcess.kill();
const parsed = JSON.parse(message);
if (parsed.type === 'start_script' && User.isAdminById(parsed.user_id)) {
if (scriptProcess) scriptProcess.kill();
const scriptPath = path.join(__dirname, '..', '..', parsed.scriptName);
if (!(await tools.isFileExistsAsync(scriptPath))) {
return ws.send(JSON.stringify({ type: 'error', data: 'Script non trovato o non autorizzato' }));
}
const scriptPath = path.join(__dirname, '..', '..', '', parsedMessage.scriptName);
// Verifica che lo script esista e sia all'interno della directory consentita
if (fs.existsSync(scriptPath)) {
scriptProcess = pty.spawn('bash', [scriptPath], {
name: 'xterm-color',
cols: 80,
@@ -992,62 +983,68 @@ connectToDatabase(connectionUrl, options)
let buffer = '';
scriptProcess.on('data', (data) => {
buffer += data;
ws.send(JSON.stringify({ type: 'output', data }));
// Invia l'output al client
ws.send(JSON.stringify({ type: 'output', data: data }));
// Controlla se c'è una richiesta di input
if (
buffer &&
(buffer.endsWith(': ') ||
buffer.endsWith(': ') ||
buffer.includes('? ') ||
buffer.toLowerCase().includes('password') ||
buffer.includes('Inserisci') ||
buffer.includes('Inserted') ||
buffer.includes('(Y'))
buffer.includes('(Y)')
) {
ws.send(JSON.stringify({ type: 'input_required', prompt: data.trim() }));
buffer = '';
}
// Pulisci il buffer se diventa troppo grande
if (buffer.length > 5024) {
buffer = buffer.slice(-500);
}
if (buffer.length > 5024) buffer = buffer.slice(-500);
});
scriptProcess.on('exit', (code) => {
if (code === 0) {
ws.send(JSON.stringify({ type: 'close', data: `*** FINE SCRIPT ***` }));
} else {
ws.send(JSON.stringify({ type: 'close', data: `Script terminato con codice ${code}` }));
}
const closeMsg = code === 0 ? '*** FINE SCRIPT ***' : `Script terminato con codice ${code}`;
ws.send(JSON.stringify({ type: 'close', data: closeMsg }));
});
} else {
ws.send(JSON.stringify({ type: 'error', data: 'Script non trovato o non autorizzato' }));
}
} else if (parsedMessage.type === 'input') {
} else if (parsed.type === 'input') {
if (scriptProcess) {
scriptProcess.write(parsedMessage.data + '\n');
scriptProcess.write(parsed.data + '\n');
}
}
} catch (error) {
console.error("Errore durante l'elaborazione del messaggio:", error.message);
} catch (err) {
console.error("Errore durante l'elaborazione del messaggio:", err.message);
}
});
ws.on('close', () => {
console.log('*** Client socket disconnected');
if (scriptProcess) {
scriptProcess.kill();
}
if (scriptProcess) scriptProcess.kill();
});
});
} else {
console.error('Nessuna Socket Aperta con WebSocket !!');
return wss;
}
} catch (e) {
console.log('error startServer: ' + e);
async function startServer(app, port) {
try {
const isProduction = ['production', 'test'].includes(process.env.NODE_ENV);
const ISDEBUG = false;
const NOCORS = false;
const { domains, domainsAllowed } = parseDomains();
console.log('domains:', domains);
console.log('isProduction:', isProduction);
const corsOptions = createCorsOptions(domains, domainsAllowed, isProduction, NOCORS);
setupMiddleware(app, corsOptions, ISDEBUG);
const server = await createHttpOrHttpsServer(app, port, isProduction, domains);
const wss = setupWebSocketServer(server);
return { server, wss };
} catch (error) {
console.error('Errore in startServer:', error);
}
}
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -163,6 +163,8 @@ module.exports = {
TABLES_MYGROUPS: 'mygroups',
TABLES_ATTIVITAS: 'attivitas',
TABLES_CATALOG: 'catalogs',
TABLES_LISTA_EDITORI: 'lista_editori',
TABLES_RACCOLTACATALOGHIS: 'raccoltacataloghis',
MYTABS: [{ id: 0, table: 'none' },
{ id: 1, table: this.TABLES_MYSKILLS },
@@ -210,7 +212,7 @@ module.exports = {
TABLES_GETCOMPLETEREC: ['myskills', 'mybachecas', 'myhosps', 'mygoods', 'attivitas'],
//++Todo: per abilitare gli utenti ad inserire un Circuito aggiungere 'circuits' alla lista TABLES_PERM_NEWREC
TABLES_PERM_NEWREC: ['skills', 'goods', 'subskills', 'mygroups', 'myhosps', 'catalogs'],
TABLES_PERM_NEWREC: ['skills', 'goods', 'subskills', 'mygroups', 'myhosps', 'catalogs', 'raccoltacataloghis'],
TABLES_REACTIONS: ['mybachecas', 'myhosps', 'myskills', 'mygoods', 'attivitas'],
@@ -223,7 +225,7 @@ module.exports = {
TABLES_GROUPS_NOTIFICATION: ['mygroups'],
TABLES_CIRCUITS_NOTIFICATION: ['circuits'],
TABLES_ENABLE_GETTABLE_FOR_NOT_LOGGED: ['attivitas', 'catalogs'],
TABLES_ENABLE_GETTABLE_FOR_NOT_LOGGED: ['attivitas', 'catalogs', 'raccoltacataloghis'],
TABLES_NUM_AS_ID_NUMBER: [],
@@ -1151,6 +1153,7 @@ module.exports = {
],
MAX_QTA_PREORD: 5000,
MAX_QTA_NON_IMPOSTATA: -1,
STATUSSKILL_DI_PERSONA: 1,
STATUSSKILL_ONLINE: 2,
@@ -1217,8 +1220,15 @@ module.exports = {
END_NORMALLY: 1,
END_WITHERROR: -50,
TOOLONGTIME: -10,
}
},
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
PUNTI_PER_POLLICE: 96,
SCONTI_APPLICA: {
NESSUNO: 0,
A_TUTTI: 1,
}
};

View File

@@ -1 +1 @@
1.2.42
1.2.67

512
yarn.lock
View File

@@ -1013,6 +1013,19 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@puppeteer/browsers@2.10.5":
version "2.10.5"
resolved "https://registry.yarnpkg.com/@puppeteer/browsers/-/browsers-2.10.5.tgz#dddb8f8716ae6364f6f2d31125e76f311dd4a49d"
integrity sha512-eifa0o+i8dERnngJwKrfp3dEq7ia5XFyoqB17S4gK8GhsQE4/P8nxOfQSE0zQHxzzLo/cmF+7+ywEQ7wK7Fb+w==
dependencies:
debug "^4.4.1"
extract-zip "^2.0.1"
progress "^2.0.3"
proxy-agent "^6.5.0"
semver "^7.7.2"
tar-fs "^3.0.8"
yargs "^17.7.2"
"@selderee/plugin-htmlparser2@^0.11.0":
version "0.11.0"
resolved "https://registry.yarnpkg.com/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.11.0.tgz#d5b5e29a7ba6d3958a1972c7be16f4b2c188c517"
@@ -1050,6 +1063,11 @@
resolved "https://registry.yarnpkg.com/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz#821f8442f4175d8f0467b9daf26e3a18e2d02af2"
integrity sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==
"@tootallnate/quickjs-emscripten@^0.23.0":
version "0.23.0"
resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c"
integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==
"@types/babel__core@^7.1.14":
version "7.20.5"
resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017"
@@ -1193,6 +1211,13 @@
dependencies:
"@types/yargs-parser" "*"
"@types/yauzl@^2.9.1":
version "2.10.3"
resolved "https://registry.yarnpkg.com/@types/yauzl/-/yauzl-2.10.3.tgz#e9b2808b4f109504a03cda958259876f61017999"
integrity sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==
dependencies:
"@types/node" "*"
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -1235,6 +1260,11 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
adler-32@~1.3.0:
version "1.3.1"
resolved "https://registry.yarnpkg.com/adler-32/-/adler-32-1.3.1.tgz#1dbf0b36dda0012189a32b3679061932df1821e2"
integrity sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==
agent-base@^7.1.0, agent-base@^7.1.2:
version "7.1.3"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-7.1.3.tgz#29435eb821bc4194633a5b89e5bc4703bafc25a1"
@@ -1495,6 +1525,13 @@ assign-symbols@^1.0.0:
resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367"
integrity sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==
ast-types@^0.13.4:
version "0.13.4"
resolved "https://registry.yarnpkg.com/ast-types/-/ast-types-0.13.4.tgz#ee0d77b343263965ecc3fb62da16e7222b2b6782"
integrity sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==
dependencies:
tslib "^2.0.1"
async-done@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/async-done/-/async-done-2.0.0.tgz#f1ec5df738c6383a52b0a30d0902fd897329c15a"
@@ -1653,11 +1690,39 @@ balanced-match@^1.0.0:
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
bare-events@^2.2.0:
bare-events@^2.2.0, bare-events@^2.5.4:
version "2.5.4"
resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.4.tgz#16143d435e1ed9eafd1ab85f12b89b3357a41745"
integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA==
bare-fs@^4.0.1:
version "4.1.5"
resolved "https://registry.yarnpkg.com/bare-fs/-/bare-fs-4.1.5.tgz#1d06c076e68cc8bf97010d29af9e3ac3808cdcf7"
integrity sha512-1zccWBMypln0jEE05LzZt+V/8y8AQsQQqxtklqaIyg5nu6OAYFhZxPXinJTSG+kU5qyNmeLgcn9AW7eHiCHVLA==
dependencies:
bare-events "^2.5.4"
bare-path "^3.0.0"
bare-stream "^2.6.4"
bare-os@^3.0.1:
version "3.6.1"
resolved "https://registry.yarnpkg.com/bare-os/-/bare-os-3.6.1.tgz#9921f6f59edbe81afa9f56910658422c0f4858d4"
integrity sha512-uaIjxokhFidJP+bmmvKSgiMzj2sV5GPHaZVAIktcxcpCyBFFWO+YlikVAdhmUo2vYFvFhOXIAlldqV29L8126g==
bare-path@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/bare-path/-/bare-path-3.0.0.tgz#b59d18130ba52a6af9276db3e96a2e3d3ea52178"
integrity sha512-tyfW2cQcB5NN8Saijrhqn0Zh7AnFNsnczRcuWODH0eYAXBsJ5gVxAUuNr7tsHSC6IZ77cA0SitzT+s47kot8Mw==
dependencies:
bare-os "^3.0.1"
bare-stream@^2.6.4:
version "2.6.5"
resolved "https://registry.yarnpkg.com/bare-stream/-/bare-stream-2.6.5.tgz#bba8e879674c4c27f7e27805df005c15d7a2ca07"
integrity sha512-jSmxKJNJmHySi6hC42zlZnq00rga4jjxcgNZjY9N5WlOe/iOoGRtdwGsHzQv2RlH2KOYMwGUXhf2zXd32BA9RA==
dependencies:
streamx "^2.21.0"
base64-js@^1.3.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
@@ -1668,7 +1733,7 @@ base64id@2.0.0, base64id@~2.0.0:
resolved "https://registry.yarnpkg.com/base64id/-/base64id-2.0.0.tgz#2770ac6bc47d312af97a8bf9a634342e0cd25cb6"
integrity sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==
basic-ftp@^5.0.5:
basic-ftp@^5.0.2, basic-ftp@^5.0.5:
version "5.0.5"
resolved "https://registry.yarnpkg.com/basic-ftp/-/basic-ftp-5.0.5.tgz#14a474f5fffecca1f4f406f1c26b18f800225ac0"
integrity sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==
@@ -1904,6 +1969,11 @@ bson@^6.10.3:
resolved "https://registry.yarnpkg.com/bson/-/bson-6.10.3.tgz#5f9a463af6b83e264bedd08b236d1356a30eda47"
integrity sha512-MTxGsqgYTwfshYWTRdmZRC+M7FnG1b4y7RO7p2k3X24Wq0yv1m77Wsj0BzlPzd/IowgESfsruQCUToa7vbOpPQ==
buffer-crc32@~0.2.3:
version "0.2.13"
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
buffer-equal-constant-time@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
@@ -2017,6 +2087,14 @@ centra@^2.7.0:
dependencies:
follow-redirects "^1.15.6"
cfb@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/cfb/-/cfb-1.2.2.tgz#94e687628c700e5155436dac05f74e08df23bc44"
integrity sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==
dependencies:
adler-32 "~1.3.0"
crc-32 "~1.2.0"
chalk@4.1.2, chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
@@ -2102,6 +2180,23 @@ cheerio@^0.22.0:
lodash.reject "^4.4.0"
lodash.some "^4.4.0"
cheerio@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-1.0.0.tgz#1ede4895a82f26e8af71009f961a9b8cb60d6a81"
integrity sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==
dependencies:
cheerio-select "^2.1.0"
dom-serializer "^2.0.0"
domhandler "^5.0.3"
domutils "^3.1.0"
encoding-sniffer "^0.2.0"
htmlparser2 "^9.1.0"
parse5 "^7.1.2"
parse5-htmlparser2-tree-adapter "^7.0.0"
parse5-parser-stream "^7.1.2"
undici "^6.19.5"
whatwg-mimetype "^4.0.0"
chokidar@^3.5.1, chokidar@^3.5.2, chokidar@^3.5.3:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -2122,6 +2217,14 @@ chownr@^1.1.4:
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
chromium-bidi@5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/chromium-bidi/-/chromium-bidi-5.1.0.tgz#8d0e47f7ac9270262df29792318dd5378e983e62"
integrity sha512-9MSRhWRVoRPDG0TgzkHrshFSJJNZzfY5UFqUMuksg7zL1yoZIZ3jLB0YAgHclbiAxPI86pBnwDX1tbzoiV8aFw==
dependencies:
mitt "^3.0.1"
zod "^3.24.1"
ci-info@^3.2.0, ci-info@^3.8.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4"
@@ -2201,6 +2304,11 @@ code-point-at@^1.0.0:
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
integrity sha512-RpAVKQA5T63xEj6/giIbUEtZwJ4UFIc3ZtvEkiaUERylqe8xb5IvqcgOurZLahv93CLKfxcw5YI+DZcUBRyLXA==
codepage@~1.15.0:
version "1.15.0"
resolved "https://registry.yarnpkg.com/codepage/-/codepage-1.15.0.tgz#2e00519024b39424ec66eeb3ec07227e692618ab"
integrity sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==
collect-v8-coverage@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz#c0b29bcd33bcd0779a1344c2136051e6afd3d9e9"
@@ -2273,6 +2381,14 @@ component-emitter@^1.3.0:
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17"
integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==
compress-pdf@^0.5.3:
version "0.5.3"
resolved "https://registry.yarnpkg.com/compress-pdf/-/compress-pdf-0.5.3.tgz#15a8c5d43f2241437a1ad42306955ccb9319367e"
integrity sha512-LeDPmE+o0PwxzqLU/uGIsaLxmnzZy4lXaY0tBov03uhNgXV6dZjU3VTBy3LhAhiCV+moXyBBE9kCDOZzZcEobg==
dependencies:
dotenv "16.4.7"
lodash "4.17.21"
concat-map@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
@@ -2399,11 +2515,26 @@ cors@^2.8.5, cors@~2.8.5:
object-assign "^4"
vary "^1"
cosmiconfig@^9.0.0:
version "9.0.0"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-9.0.0.tgz#34c3fc58287b915f3ae905ab6dc3de258b55ad9d"
integrity sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==
dependencies:
env-paths "^2.2.1"
import-fresh "^3.3.0"
js-yaml "^4.1.0"
parse-json "^5.2.0"
country-codes-list@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/country-codes-list/-/country-codes-list-2.0.0.tgz#162c49028a0a9fe64503ed146980e0bb8529c170"
integrity sha512-KZqq/LBdCD76hQCa6nOx0bA/nIjYly1OtV8+Bbt/4SW+mJEqGk7oZHjUj7PRrV0gXJJKs6Tv2cIntFdofBByvA==
crc-32@~1.2.0, crc-32@~1.2.1:
version "1.2.2"
resolved "https://registry.yarnpkg.com/crc-32/-/crc-32-1.2.2.tgz#3cad35a934b8bf71f25ca524b6da51fb7eace2ff"
integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
create-jest@^29.7.0:
version "29.7.0"
resolved "https://registry.yarnpkg.com/create-jest/-/create-jest-29.7.0.tgz#a355c5b3cb1e1af02ba177fe7afd7feee49a5320"
@@ -2542,6 +2673,11 @@ dashdash@^1.12.0:
dependencies:
assert-plus "^1.0.0"
data-uri-to-buffer@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz#8a58bb67384b261a38ef18bea1810cb01badd28b"
integrity sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==
data-urls@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/data-urls/-/data-urls-5.0.0.tgz#2f76906bce1824429ffecb6920f45a0b30f00dde"
@@ -2598,6 +2734,13 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7:
dependencies:
ms "^2.1.1"
debug@^4.4.1:
version "4.4.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==
dependencies:
ms "^2.1.3"
debug@~4.3.1, debug@~4.3.2, debug@~4.3.4:
version "4.3.7"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.7.tgz#87945b4151a011d76d95a198d7111c865c360a52"
@@ -2671,6 +2814,15 @@ define-properties@^1.2.1:
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
degenerator@^5.0.0:
version "5.0.1"
resolved "https://registry.yarnpkg.com/degenerator/-/degenerator-5.0.1.tgz#9403bf297c6dad9a1ece409b37db27954f91f2f5"
integrity sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==
dependencies:
ast-types "^0.13.4"
escodegen "^2.1.0"
esprima "^4.0.1"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
@@ -2726,6 +2878,11 @@ dev-ip@^1.0.1:
resolved "https://registry.yarnpkg.com/dev-ip/-/dev-ip-1.0.1.tgz#a76a3ed1855be7a012bb8ac16cb80f3c00dc28f0"
integrity sha512-LmVkry/oDShEgSZPNgqCIp2/TlqtExeGmymru3uCELnfyjY11IzpAproLYs+1X88fXO6DBoYP3ul2Xo2yz2j6A==
devtools-protocol@0.0.1439962:
version "0.0.1439962"
resolved "https://registry.yarnpkg.com/devtools-protocol/-/devtools-protocol-0.0.1439962.tgz#395c5ca1cd83aa451c667056a025f9873c4598c1"
integrity sha512-jJF48UdryzKiWhJ1bLKr7BFWUQCEIT5uCNbDLqkQJBtkFxYzILJH44WN0PDKMIlGDN7Utb8vyUY85C3w4R/t2g==
dezalgo@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/dezalgo/-/dezalgo-1.0.4.tgz#751235260469084c132157dfa857f386d4c33d81"
@@ -2874,7 +3031,7 @@ domutils@^2.4.2:
domelementtype "^2.2.0"
domhandler "^4.2.0"
domutils@^3.0.1:
domutils@^3.0.1, domutils@^3.1.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.2.tgz#edbfe2b668b0c1d97c24baf0f1062b132221bc78"
integrity sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==
@@ -2883,7 +3040,7 @@ domutils@^3.0.1:
domelementtype "^2.3.0"
domhandler "^5.0.3"
dotenv@^16.4.7:
dotenv@16.4.7, dotenv@^16.4.7:
version "16.4.7"
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26"
integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==
@@ -3011,6 +3168,14 @@ encoding-japanese@2.2.0:
resolved "https://registry.yarnpkg.com/encoding-japanese/-/encoding-japanese-2.2.0.tgz#0ef2d2351250547f432a2dd155453555c16deb59"
integrity sha512-EuJWwlHPZ1LbADuKTClvHtwbaFn4rOD+dRAbWysqEOXRc2Uui0hJInNJrsdH0c+OhJA4nrCBdSkW4DD5YxAo6A==
encoding-sniffer@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz#799569d66d443babe82af18c9f403498365ef1d5"
integrity sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==
dependencies:
iconv-lite "^0.6.3"
whatwg-encoding "^3.1.1"
end-of-stream@^1.1.0, end-of-stream@^1.4.4:
version "1.4.4"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
@@ -3064,6 +3229,16 @@ entities@^4.2.0, entities@^4.4.0, entities@^4.5.0:
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
entities@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-6.0.0.tgz#09c9e29cb79b0a6459a9b9db9efb418ac5bb8e51"
integrity sha512-aKstq2TDOndCn4diEyp9Uq/Flu2i1GlLkc6XIDQSDMuaFE3OPW5OphLCyQ5SpSJZTb4reN+kTcYru5yIfXoRPw==
env-paths@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.1.tgz#420399d416ce1fbe9bc0a07c62fa68d67fd0f8f2"
integrity sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==
error-ex@^1.3.1:
version "1.3.2"
resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf"
@@ -3216,12 +3391,23 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escodegen@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17"
integrity sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==
dependencies:
esprima "^4.0.1"
estraverse "^5.2.0"
esutils "^2.0.2"
optionalDependencies:
source-map "~0.6.1"
esprima@^1.2.0:
version "1.2.5"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-1.2.5.tgz#0993502feaf668138325756f30f9a51feeec11e9"
integrity sha512-S9VbPDU0adFErpDai3qDkjq8+G05ONtKzcyNrPKg/ZKa+tf879nX2KexNU95b31UoTJjRLInNBHHHjFPoCd7lQ==
esprima@^4.0.0:
esprima@^4.0.0, esprima@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71"
integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==
@@ -3231,6 +3417,16 @@ estraverse@^1.5.0:
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-1.9.3.tgz#af67f2dc922582415950926091a4005d29c9bb44"
integrity sha512-25w1fMXQrGdoquWnScXZGckOv+Wes+JDnuN/+7ex3SauFRS72r2lFDec0EKPt2YD1wUJ/IrfEex+9yp4hfSOJA==
estraverse@^5.2.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123"
integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==
etag@1.8.1, etag@^1.8.1, etag@~1.8.1:
version "1.8.1"
resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
@@ -3390,6 +3586,17 @@ extract-css@^2.0.0:
list-stylesheets "^1.2.10"
style-data "^1.4.8"
extract-zip@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a"
integrity sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==
dependencies:
debug "^4.1.1"
get-stream "^5.1.0"
yauzl "^2.10.0"
optionalDependencies:
"@types/yauzl" "^2.9.1"
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
@@ -3415,7 +3622,7 @@ fast-deep-equal@^3.1.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
fast-fifo@^1.3.2:
fast-fifo@^1.2.0, fast-fifo@^1.3.2:
version "1.3.2"
resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c"
integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==
@@ -3461,6 +3668,13 @@ fb-watchman@^2.0.0:
dependencies:
bser "2.1.1"
fd-slicer@~1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e"
integrity sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==
dependencies:
pend "~1.2.0"
file-type@^3.1.0, file-type@^3.9.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
@@ -3658,6 +3872,11 @@ forwarded@0.2.0:
resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
integrity sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==
frac@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/frac/-/frac-1.1.2.tgz#3d74f7f6478c88a1b5020306d747dc6313c74d0b"
integrity sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==
fresh@0.5.2, fresh@^0.5.2:
version "0.5.2"
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
@@ -3794,6 +4013,13 @@ get-stream@^3.0.0:
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14"
integrity sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==
get-stream@^5.1.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.2.0.tgz#4966a1795ee5ace65e706c4b7beb71257d6e22d3"
integrity sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==
dependencies:
pump "^3.0.0"
get-stream@^6.0.0:
version "6.0.1"
resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7"
@@ -3808,6 +4034,15 @@ get-symbol-description@^1.1.0:
es-errors "^1.3.0"
get-intrinsic "^1.2.6"
get-uri@^6.0.1:
version "6.0.4"
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-6.0.4.tgz#6daaee9e12f9759e19e55ba313956883ef50e0a7"
integrity sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==
dependencies:
basic-ftp "^5.0.2"
data-uri-to-buffer "^6.0.2"
debug "^4.3.4"
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
@@ -4175,6 +4410,16 @@ htmlparser2@^8.0.0, htmlparser2@^8.0.1, htmlparser2@^8.0.2:
domutils "^3.0.1"
entities "^4.4.0"
htmlparser2@^9.1.0:
version "9.1.0"
resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-9.1.0.tgz#cdb498d8a75a51f739b61d3f718136c369bc8c23"
integrity sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==
dependencies:
domelementtype "^2.3.0"
domhandler "^5.0.3"
domutils "^3.1.0"
entities "^4.5.0"
http-errors@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-2.0.0.tgz#b7774a1486ef73cf7667ac9ae0858c012c57b9d3"
@@ -4207,7 +4452,7 @@ http-errors@~1.7.3:
statuses ">= 1.5.0 < 2"
toidentifier "1.0.0"
http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.2:
http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1, http-proxy-agent@^7.0.2:
version "7.0.2"
resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e"
integrity sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==
@@ -4334,6 +4579,14 @@ immutable@^3:
resolved "https://registry.yarnpkg.com/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3"
integrity sha512-15gZoQ38eYjEjxkorfbcgBKBL6R7T459OuK+CpcWt7O3KF4uPCx2tD0uFETlUDIyo+1789crbMhTvQBSR5yBMg==
import-fresh@^3.3.0:
version "3.3.1"
resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.1.tgz#9cecb56503c0ada1f2741dbbd6546e4b13b57ccf"
integrity sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==
dependencies:
parent-module "^1.0.0"
resolve-from "^4.0.0"
import-local@^3.0.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.2.0.tgz#c3d5c745798c02a6f8b897726aba5100186ee260"
@@ -4404,6 +4657,14 @@ interpret@^3.1.1:
resolved "https://registry.yarnpkg.com/interpret/-/interpret-3.1.1.tgz#5be0ceed67ca79c6c4bc5cf0d7ee843dcea110c4"
integrity sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==
ip-address@^9.0.5:
version "9.0.5"
resolved "https://registry.yarnpkg.com/ip-address/-/ip-address-9.0.5.tgz#117a960819b08780c3bd1f14ef3c1cc1d3f3ea5a"
integrity sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==
dependencies:
jsbn "1.1.0"
sprintf-js "^1.1.3"
ip-regex@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
@@ -5323,6 +5584,11 @@ js-yaml@^4.1.0:
dependencies:
argparse "^2.0.1"
jsbn@1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-1.1.0.tgz#b01307cb29b618a1ed26ec79e911f803c4da0040"
integrity sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
@@ -5727,7 +5993,7 @@ lodash.some@^4.4.0:
resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d"
integrity sha512-j7MJE+TuT51q9ggt4fSgVqro163BEFjAt3u97IqU+JA2DkWl80nFTrowzLpZ/BnpN7rrl0JA/593NAdd8p/scQ==
lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21:
lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -5757,6 +6023,11 @@ lru-cache@^5.1.1:
dependencies:
yallist "^3.0.2"
lru-cache@^7.14.1:
version "7.18.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89"
integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==
mailparser@^3.7.1:
version "3.7.2"
resolved "https://registry.yarnpkg.com/mailparser/-/mailparser-3.7.2.tgz#00feec656e23c0ae805163581b460c2f72ca75d1"
@@ -5975,6 +6246,11 @@ mitt@^1.1.3:
resolved "https://registry.yarnpkg.com/mitt/-/mitt-1.2.0.tgz#cb24e6569c806e31bd4e3995787fe38a04fdf90d"
integrity sha512-r6lj77KlwqLhIUku9UWYes7KJtsczvolZkzp8hbaDPPaE24OmWl5s539Mytlj22siEQKosZ26qCBgda2PKwoJw==
mitt@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mitt/-/mitt-3.0.1.tgz#ea36cf0cc30403601ae074c8f77b7092cdab36d1"
integrity sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==
mkdirp@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
@@ -6159,6 +6435,11 @@ negotiator@0.6.3:
resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd"
integrity sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==
netmask@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/netmask/-/netmask-2.0.2.tgz#8b01a07644065d536383835823bc52004ebac5e7"
integrity sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==
nice-try@^1.0.4:
version "1.0.5"
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
@@ -6587,6 +6868,28 @@ p-wait-for@3.2.0:
dependencies:
p-timeout "^3.0.0"
pac-proxy-agent@^7.1.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz#9cfaf33ff25da36f6147a20844230ec92c06e5df"
integrity sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==
dependencies:
"@tootallnate/quickjs-emscripten" "^0.23.0"
agent-base "^7.1.2"
debug "^4.3.4"
get-uri "^6.0.1"
http-proxy-agent "^7.0.0"
https-proxy-agent "^7.0.6"
pac-resolver "^7.0.1"
socks-proxy-agent "^8.0.5"
pac-resolver@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/pac-resolver/-/pac-resolver-7.0.1.tgz#54675558ea368b64d210fd9c92a640b5f3b8abb6"
integrity sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==
dependencies:
degenerator "^5.0.0"
netmask "^2.0.2"
package-json-from-dist@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505"
@@ -6597,6 +6900,13 @@ pako@^1.0.10, pako@^1.0.11, pako@^1.0.6:
resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
parent-module@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2"
integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==
dependencies:
callsites "^3.0.0"
parse-bmfont-ascii@^1.0.3:
version "1.0.6"
resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285"
@@ -6662,6 +6972,13 @@ parse5-htmlparser2-tree-adapter@^7.0.0:
domhandler "^5.0.3"
parse5 "^7.0.0"
parse5-parser-stream@^7.1.2:
version "7.1.2"
resolved "https://registry.yarnpkg.com/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz#d7c20eadc37968d272e2c02660fff92dd27e60e1"
integrity sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==
dependencies:
parse5 "^7.0.0"
parse5@^7.0.0, parse5@^7.2.1:
version "7.2.1"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a"
@@ -6669,6 +6986,13 @@ parse5@^7.0.0, parse5@^7.2.1:
dependencies:
entities "^4.5.0"
parse5@^7.1.2:
version "7.3.0"
resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.3.0.tgz#d7e224fa72399c7a175099f45fc2ad024b05ec05"
integrity sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==
dependencies:
entities "^6.0.0"
parseley@^0.12.0:
version "0.12.1"
resolved "https://registry.yarnpkg.com/parseley/-/parseley-0.12.1.tgz#4afd561d50215ebe259e3e7a853e62f600683aef"
@@ -6772,6 +7096,11 @@ pem@^1.14.8:
os-tmpdir "^1.0.2"
which "^2.0.2"
pend@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
integrity sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
@@ -6898,6 +7227,11 @@ process@^0.11.10:
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
progress@^2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
integrity sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==
promise@^6.0.1:
version "6.1.0"
resolved "https://registry.yarnpkg.com/promise/-/promise-6.1.0.tgz#2ce729f6b94b45c26891ad0602c5c90e04c6eef6"
@@ -6935,6 +7269,20 @@ proxy-addr@~2.0.7:
forwarded "0.2.0"
ipaddr.js "1.9.1"
proxy-agent@^6.5.0:
version "6.5.0"
resolved "https://registry.yarnpkg.com/proxy-agent/-/proxy-agent-6.5.0.tgz#9e49acba8e4ee234aacb539f89ed9c23d02f232d"
integrity sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==
dependencies:
agent-base "^7.1.2"
debug "^4.3.4"
http-proxy-agent "^7.0.1"
https-proxy-agent "^7.0.6"
lru-cache "^7.14.1"
pac-proxy-agent "^7.1.0"
proxy-from-env "^1.1.0"
socks-proxy-agent "^8.0.5"
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
@@ -7063,6 +7411,14 @@ pump@^2.0.0:
end-of-stream "^1.1.0"
once "^1.3.1"
pump@^3.0.0:
version "3.0.2"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.2.tgz#836f3edd6bc2ee599256c924ffe0d88573ddcbf8"
integrity sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==
dependencies:
end-of-stream "^1.1.0"
once "^1.3.1"
punycode.js@2.3.1:
version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode.js/-/punycode.js-2.3.1.tgz#6b53e56ad75588234e79f4affa90972c7dd8cdb7"
@@ -7073,6 +7429,30 @@ punycode@^2.1.0, punycode@^2.1.1, punycode@^2.3.1:
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
puppeteer-core@24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/puppeteer-core/-/puppeteer-core-24.9.0.tgz#fc489e83bf65db1dc72e53a78140ee567efd847e"
integrity sha512-HFdCeH/wx6QPz8EncafbCqJBqaCG1ENW75xg3cLFMRUoqZDgByT6HSueiumetT2uClZxwqj0qS4qMVZwLHRHHw==
dependencies:
"@puppeteer/browsers" "2.10.5"
chromium-bidi "5.1.0"
debug "^4.4.1"
devtools-protocol "0.0.1439962"
typed-query-selector "^2.12.0"
ws "^8.18.2"
puppeteer@^24.9.0:
version "24.9.0"
resolved "https://registry.yarnpkg.com/puppeteer/-/puppeteer-24.9.0.tgz#1d3f805e0170ca481b637a47c71a09b815594dae"
integrity sha512-L0pOtALIx8rgDt24Y+COm8X52v78gNtBOW6EmUcEPci0TYD72SAuaXKqasRIx4JXxmg2Tkw5ySKcpPOwN8xXnQ==
dependencies:
"@puppeteer/browsers" "2.10.5"
chromium-bidi "5.1.0"
cosmiconfig "^9.0.0"
devtools-protocol "0.0.1439962"
puppeteer-core "24.9.0"
typed-query-selector "^2.12.0"
pure-rand@^6.0.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/pure-rand/-/pure-rand-6.1.0.tgz#d173cf23258231976ccbdb05247c9787957604f2"
@@ -7347,6 +7727,11 @@ resolve-dir@^1.0.0, resolve-dir@^1.0.1:
expand-tilde "^2.0.0"
global-modules "^1.0.0"
resolve-from@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
resolve-from@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
@@ -7538,6 +7923,11 @@ semver@^7.5.3, semver@^7.5.4, semver@^7.6.3:
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f"
integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==
semver@^7.7.2:
version "7.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"
integrity sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==
send@0.19.0:
version "0.19.0"
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
@@ -7806,6 +8196,11 @@ slick@^1.12.2:
resolved "https://registry.yarnpkg.com/slick/-/slick-1.12.2.tgz#bd048ddb74de7d1ca6915faa4a57570b3550c2d7"
integrity sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==
smart-buffer@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
integrity sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==
socket.io-adapter@~2.5.2:
version "2.5.5"
resolved "https://registry.yarnpkg.com/socket.io-adapter/-/socket.io-adapter-2.5.5.tgz#c7a1f9c703d7756844751b6ff9abfc1780664082"
@@ -7845,6 +8240,23 @@ socket.io@^4.4.1:
socket.io-adapter "~2.5.2"
socket.io-parser "~4.2.4"
socks-proxy-agent@^8.0.5:
version "8.0.5"
resolved "https://registry.yarnpkg.com/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz#b9cdb4e7e998509d7659d689ce7697ac21645bee"
integrity sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==
dependencies:
agent-base "^7.1.2"
debug "^4.3.4"
socks "^2.8.3"
socks@^2.8.3:
version "2.8.4"
resolved "https://registry.yarnpkg.com/socks/-/socks-2.8.4.tgz#07109755cdd4da03269bda4725baa061ab56d5cc"
integrity sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==
dependencies:
ip-address "^9.0.5"
smart-buffer "^4.2.0"
source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
@@ -7870,7 +8282,7 @@ source-map@^0.5.1, source-map@~0.5.1:
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
source-map@^0.6.0, source-map@^0.6.1:
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==
@@ -7921,6 +8333,13 @@ sqlstring@2.3.1:
resolved "https://registry.yarnpkg.com/sqlstring/-/sqlstring-2.3.1.tgz#475393ff9e91479aea62dcaf0ca3d14983a7fb40"
integrity sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==
ssf@~0.11.2:
version "0.11.2"
resolved "https://registry.yarnpkg.com/ssf/-/ssf-0.11.2.tgz#0b99698b237548d088fc43cdf2b70c1a7512c06c"
integrity sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==
dependencies:
frac "~1.1.2"
sshpk@^1.18.0, sshpk@^1.7.0:
version "1.18.0"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.18.0.tgz#1663e55cddf4d688b86a46b77f0d5fe363aba028"
@@ -8013,7 +8432,7 @@ streamsearch@^1.1.0:
resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0:
streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0, streamx@^2.15.0, streamx@^2.21.0:
version "2.22.0"
resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.22.0.tgz#cd7b5e57c95aaef0ff9b2aef7905afa62ec6e4a7"
integrity sha512-sLh1evHOzBy/iWRiR6d1zRcLao4gGZr3C1kzNz4fopCOKJb6xD9ub8Mpi9Mr1R6id5o43S+d93fI48UC5uM9aw==
@@ -8251,6 +8670,26 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
tar-fs@^3.0.8:
version "3.0.9"
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-3.0.9.tgz#d570793c6370d7078926c41fa422891566a0b617"
integrity sha512-XF4w9Xp+ZQgifKakjZYmFdkLoSWd34VGKcsTCwlNWM7QG3ZbaxnTsaBwnjFZqHRf/rROxaR8rXnbtwdvaDI+lA==
dependencies:
pump "^3.0.0"
tar-stream "^3.1.5"
optionalDependencies:
bare-fs "^4.0.1"
bare-path "^3.0.0"
tar-stream@^3.1.5:
version "3.1.7"
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-3.1.7.tgz#24b3fb5eabada19fe7338ed6d26e5f7c482e792b"
integrity sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==
dependencies:
b4a "^1.6.4"
fast-fifo "^1.2.0"
streamx "^2.15.0"
tar@^4.4.13:
version "4.4.19"
resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.19.tgz#2e4d7263df26f2b914dee10c825ab132123742f3"
@@ -8447,7 +8886,7 @@ tslib@^1.11.1:
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00"
integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==
tslib@^2.2.0, tslib@^2.4.0, tslib@^2.6.2:
tslib@^2.0.1, tslib@^2.2.0, tslib@^2.4.0, tslib@^2.6.2:
version "2.8.1"
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f"
integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==
@@ -8532,6 +8971,11 @@ typed-array-length@^1.0.7:
possible-typed-array-names "^1.0.0"
reflect.getprototypeof "^1.0.6"
typed-query-selector@^2.12.0:
version "2.12.0"
resolved "https://registry.yarnpkg.com/typed-query-selector/-/typed-query-selector-2.12.0.tgz#92b65dbc0a42655fccf4aeb1a08b1dddce8af5f2"
integrity sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==
typedarray@^0.0.6:
version "0.0.6"
resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777"
@@ -8632,6 +9076,11 @@ undici-types@~6.20.0:
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433"
integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==
undici@^6.19.5:
version "6.21.3"
resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.3.tgz#185752ad92c3d0efe7a7d1f6854a50f83b552d7a"
integrity sha512-gBLkYIlEnSp8pFbT64yFgGE6UIB9tAkhukC23PmMDCe5Nd+cRqKxSjw5y54MK2AZMgZfJWMaNE4nYUHgi1XEOw==
unicode-emoji-modifier-base@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz#dbbd5b54ba30f287e2a8d5a249da6c0cef369459"
@@ -9020,6 +9469,16 @@ with@~4.0.0:
acorn "^1.0.1"
acorn-globals "^1.0.3"
wmf@~1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wmf/-/wmf-1.0.2.tgz#7d19d621071a08c2bdc6b7e688a9c435298cc2da"
integrity sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==
word@~0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/word/-/word-0.3.0.tgz#8542157e4f8e849f4a363a288992d47612db9961"
integrity sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==
wordwrap@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-0.0.2.tgz#b79669bb42ecb409f83d583cad52ca17eaa1643f"
@@ -9080,6 +9539,11 @@ ws@^8.18.0:
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.1.tgz#ea131d3784e1dfdff91adb0a4a116b127515e3cb"
integrity sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==
ws@^8.18.2:
version "8.18.2"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.2.tgz#42738b2be57ced85f46154320aabb51ab003705a"
integrity sha512-DMricUmwGZUVr++AEAe2uiVM7UoO9MAVZMDu05UQOaUII0lp+zOzLLU4Xqh/JvTqklB1T4uELaaPBKyjE1r4fQ==
ws@~8.17.1:
version "8.17.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.1.tgz#9293da530bb548febc95371d90f9c878727d919b"
@@ -9095,6 +9559,19 @@ xhr@^2.0.1:
parse-headers "^2.0.0"
xtend "^4.0.0"
xlsx@^0.18.5:
version "0.18.5"
resolved "https://registry.yarnpkg.com/xlsx/-/xlsx-0.18.5.tgz#16711b9113c848076b8a177022799ad356eba7d0"
integrity sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==
dependencies:
adler-32 "~1.3.0"
cfb "~1.2.1"
codepage "~1.15.0"
crc-32 "~1.2.1"
ssf "~0.11.2"
wmf "~1.0.1"
word "~0.3.0"
xml-name-validator@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-5.0.0.tgz#82be9b957f7afdacf961e5980f1bf227c0bf7673"
@@ -9212,7 +9689,20 @@ yargs@~3.10.0:
decamelize "^1.0.0"
window-size "0.1.0"
yauzl@^2.10.0:
version "2.10.0"
resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9"
integrity sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==
dependencies:
buffer-crc32 "~0.2.3"
fd-slicer "~1.1.0"
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"
integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==
zod@^3.24.1:
version "3.25.32"
resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.32.tgz#769cc684072df780fc8f38130b0cd9283a8d3818"
integrity sha512-OSm2xTIRfW8CV5/QKgngwmQW/8aPfGdaQFlrGoErlgg/Epm7cjb6K6VEyExfe65a3VybUOnu381edLb0dfJl0g==