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

@@ -835,4 +835,6 @@ https://t.me/riso_canale/739
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
✅ 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

@@ -1,4 +1,4 @@
const fs = require('fs');
const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
var FILE = require('./file');

File diff suppressed because it is too large Load Diff

View File

@@ -21,7 +21,8 @@ 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;
console.log(` ## ${logPrefix}_TOKEN INVALIDO ❌ ...`);
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()
.then(() => { })
.catch((err) => { throw err; });
module.exports
.createIndexes()
.then(() => {})
.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 Order = require('../models/order');
const mycart = await getCart(uid, idapp);
if (!mycart) return null;
let query = { userId: uid, idapp };
const mycart = await Cart.findOne(query).lean();
await updateOrderDetails(mycart.items);
filterValidItems(mycart);
if (!!mycart) {
for (const idkey in mycart.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);
if (myord.length > 0) {
mycart.items[idkey].order = myord[0];
}
}
} catch (e) {
console.log('err', e);
}
}
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)
}
mycart.items = [...mycart.newitems]
mycart.newitems = []
return mycart;
}
return null;
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');
for (const item of items) {
try {
const idorder = item.order ? item.order._id.toString() : item._id.toString();
const myord = await Order.getTotalOrderById(idorder);
if (myord.length > 0) {
item.order = myord[0];
}
} catch (e) {
console.log('err', e);
}
}
}
// 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);
}
}
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 }, {
$set: {
items,
totalPrice,
totalPriceCalc,
totalQty,
note,
note_ordine_gas,
modify_at: new Date(),
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) => {
return ris;
}).catch(err => {
console.log('err', err);
return null;
});
{ new: false }
)
.lean()
.then((ris) => {
return ris;
})
.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; });
.then(() => {})
.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: [{
type: String,
}],
idTipoFormato: [{
type: Number,
}],
idCollane: [
{
type: String,
},
],
idTipoFormato: [
{
type: Number,
},
],
argomenti: [{
type: String,
}],
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: {
type: String,
},
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: [{
type: Schema.Types.ObjectId,
ref: 'Product',
}],
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);
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; });
.then(() => {})
.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,94 +6,91 @@ 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(
{
imagefile: String,
vers_img: Number,
alt: String,
description: String,
style: String,
size: String,
color: String,
content: String,
colorsub: String,
link: String,
}
)
const animation = new Schema(
{
name: String,
clduration: String,
cldelay: String,
timingtype: String,
}
);
const myCard = new Schema({
imagefile: String,
vers_img: Number,
alt: String,
description: String,
style: String,
size: String,
color: String,
content: String,
colorsub: String,
link: String,
});
const animation = new Schema({
name: String,
clduration: String,
cldelay: String,
timingtype: String,
});
const elemText = new Schema(
{
text: String,
color: String,
class: String,
size: String,
anim: animation,
}
);
const elemText = new Schema({
text: String,
color: String,
class: String,
size: String,
anim: animation,
});
const catalogo = new Schema({
//++AddCATALOGO_FIELDS
idCatalogSel: { type: String },
productTypes: [{ type: Number }],
excludeproductTypes: [{ type: Number }],
editore: [{ type: String }],
argomenti: [{ type: String }],
idCollane: [{ type: String }],
idTipologia: [{ type: Number }],
idTipoFormato: [{ type: Number }],
sort_field: { type: String },
sort_dir: { type: Number },
pdf: { type: Boolean },
pdf_filename: { type: String },
printable: { type: Boolean },
indebug: { type: Boolean },
maxnumlibri: { type: Number },
showListaArgomenti: { type: Boolean },
showOnlyCatalogoPDF: { type: Boolean },
showListaCollane: { type: Boolean },
const catalogo = new Schema(
{
//++AddCATALOGO_FIELDS
productTypes: [{ type: Number }],
excludeproductTypes: [{ type: Number }],
editore: [{ type: String }],
argomenti: [{ type: String }],
idCollane: [{ type: String }],
idTipologia: [{ type: Number }],
idTipoFormato: [{ type: Number }],
sort_field: { type: String },
sort_dir: { type: Number },
pdf: { type: Boolean },
pdf_filename: { type: String },
printable: { type: Boolean },
indebug: { type: Boolean },
maxnumlibri: { type: Number },
showListaArgomenti: { type: Boolean},
showListaCollane: { type: Boolean},
first_page: IDimensioni,
last_page: IDimensioni,
areadistampa: IAreaDiStampa,
first_page: IDimensioni,
last_page: IDimensioni,
areadistampa: IAreaDiStampa,
print_isTemplate: Boolean,
print_linkIdTemplate: String,
dimensioni_def: IElementiPagina,
dimensioni_def: IElementiPagina,
// -------------------
arrSchede: [
{
scheda: MySchedaSchema,
order: { type: Number },
numPagineMax: { type: Number },
/*arrProdToShow: {
// -------------------
arrSchede: [
{
scheda: MySchedaSchema,
order: { type: Number },
numPagineMax: { type: Number },
/*arrProdToShow: {
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 existingPages = await MyPage.find({ idapp }).select('_id').lean();
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 => ({
...scheda, // mantieni i dati originali della scheda
idPageOrig: elem.idPage // aggiungi l'idPage
}))
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
}))
: []
);
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;
@@ -537,8 +552,9 @@ MyElemSchema.statics.getNewFreeNameTemplate = async function (idapp, idPageOrig,
const MyElem = mongoose.model('MyElem', MyElemSchema);
MyElem.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
.then(() => {})
.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: [{
type: Number,
}],
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({
idapp,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow).lean();
return await MyGroup.find(
{
idapp,
$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 },
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{
$push:
{
$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 },
return await MyGroup.updateOne(
{ idapp, groupname: groupnameDest },
{
$push:
{
$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({
idapp,
groupname,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, { admins: 1 }).lean();
let arr = await MyGroup.findOne(
{
idapp,
groupname,
$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({
idapp,
groupname,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
}, myobj);
const ris = await User.findOne(
{
idapp,
groupname,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
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({
idapp,
username: { $in: arrUsernameGroups },
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow);
let listUsersGroup = await User.find(
{
idapp,
username: { $in: arrUsernameGroups },
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
whatToShow
);
let listgroups = await MyGroup.find({
idapp,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
let listgroups = await MyGroup.find(
{
idapp,
$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({
idapp,
'req_users': {
$elemMatch: { username: { $eq: username } },
let listSentRequestGroups = await MyGroup.find(
{
idapp,
req_users: {
$elemMatch: { username: { $eq: username } },
},
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
whatToShow_Unknown
);
let listRefusedGroups = await MyGroup.find({
idapp,
'refused_users': {
$elemMatch: { username: { $eq: username } },
let listRefusedGroups = await MyGroup.find(
{
idapp,
refused_users: {
$elemMatch: { username: { $eq: username } },
},
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
},
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
}, whatToShow_Unknown);
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();
@@ -675,8 +658,9 @@ MyGroupSchema.statics.setReceiveRisGroup = async function (idapp, groupname) {
const MyGroup = mongoose.model('MyGroup', MyGroupSchema);
MyGroup.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
.then(() => {})
.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);
module.exports.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
var Order = (module.exports = mongoose.model('Order', orderSchema));
module.exports
.createIndexes()
.then(() => {})
.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;
return null;
});
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
} else {
qtanonscontata = qtadascontare
qtadascontare = 0
}
}
/*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;
}
// 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 {
mypricecalc = (order.price * order.quantity) + (order.price * order.quantitypreordered);
total = OrderClass.calculateFullPrice(order);
}
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] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
]
}]
}
]
}
]
}
$and: [
{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] }, // 1 hour in milliseconds 60 * 60
],
},
],
},
],
},
],
},
},
},
{
$group: {
_id: null,
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] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
]
}]
}
]
}
]
}
}
$and: [
{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] }, // 1 hour in milliseconds 60 * 60
],
},
],
},
],
},
],
},
},
},
{
$group: {
_id: null,
totalQtyPreordered: { $sum: '$quantitypreordered' }
}
}
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: {
@@ -707,67 +667,57 @@ 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.active': true }, // Include documents where gasordines.active is true
{ 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,53 +13,55 @@ 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({
_id: {
type: Number,
},
reg: {
type: String,
},
prov: {
type: String,
// unique: true,
maxlength: 3,
},
descr: {
type: String,
},
link_grp: {
type: String,
},
card: {
type: String,
},
const ProvinceSchema = new Schema(
{
_id: {
type: Number,
},
reg: {
type: String,
},
prov: {
type: String,
// unique: true,
maxlength: 3,
},
idCircuitToAssign: {
type: String,
},
descr: {
type: String,
},
link_grp: {
type: String,
},
card: {
type: String,
},
link_telegram: {
type: String,
link_telegram: {
type: String,
},
lat: {
type: Number,
},
long: {
type: Number,
},
},
lat: {
type: Number,
},
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; });
.then(() => {})
.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
if (myproduct.quantityAvailable > 0) {
if (myorder.quantity === minqta)
step = minqta
else {
if ((myorder.quantity - step) < 0)
step = myorder.quantity - step
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;
}
}
} else {
if (myorder.quantitypreordered === minqta) {
step = minqta;
}
step = myorder.quantity - stepΩ;
}
} else {
if (myorder.quantitypreordered === minqta)
step = minqta
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,112 +207,77 @@ 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;
async updateOrderTotals(order, updateCalcPrice) {
order.TotalPriceProductCalc = 0;
let order = this.items[rec].order;
if (!order) {
order = this.items[rec];
}
order.TotalPriceProductCalc = 0;
if (updatecalcprice) {
order.TotalPriceProduct = 0;
}
this.totalQty += order.quantity + order.quantitypreordered;
// PROVO A METTERE SEMPRE CHE MI RICALCOLA IL PREZZO !
// updateCalcPrice = true;
// 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
} else {
qtanonscontata = qtadascontare
qtadascontare = 0
}
}
/*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);
}
// Aggiorna Totali
order.TotalPriceProductCalc += mypricecalc;
if (updatecalcprice) {
order.TotalPriceProduct += mypricecalc;
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))
} catch (e) {
console.error('Err: ', e);
if (updateCalcPrice) {
order.TotalPriceProduct = 0;
}
const qty = order.quantity + order.quantitypreordered;
this.totalQty += qty;
const recscontisticheTrovate = await Cart.getRecSconto(this.idapp, this.codice_sconto, true);
const scontiDaUsare = recscontisticheTrovate?.length ? recscontisticheTrovate : order.scontisticas || [];
const priceCalc = this.calcolaPrezzoScontato(order, qty, scontiDaUsare);
const priceintero = this.calcolaPrezzoScontato(order, qty, []);
order.TotalPriceProductCalc += priceCalc;
if (updateCalcPrice) {
order.TotalPriceProduct += priceCalc;
order.TotalPriceProductstr = parseFloat(order.TotalPriceProduct.toFixed(2));
}
this.totalPrice += order.TotalPriceProduct;
this.totalPriceCalc += priceCalc;
this.totalPriceIntero += priceintero;
// 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) {
for (const rec in this.items) {
let order = this.items[rec].order;
if (!order) {
order = this.items[rec];
@@ -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;
}
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
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;

File diff suppressed because it is too large Load Diff

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,16 +148,7 @@ 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`);
}
// Costruisci il comando ps2pdf
const ps2pdfCommand = `ps2pdf -dPDFSETTINGS=/${compression} "${inputFile}" "${outputFile}"`;
console.log(`Eseguendo: ${ps2pdfCommand}`);
// 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);
}
// Converti cm in punti (1 cm = 28.34646 punti)
const widthPt = width * 28.34646;
const heightPt = height * 28.34646;
// Arrotonda i valori
const widthPx = Math.round(widthPt);
const heightPx = Math.round(heightPt);
// Comando Ghostscript
const gsCommand = [
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
'-dPDFSETTINGS=/prepress',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
`-dDEVICEWIDTHPOINTS=${widthPx}`,
`-dDEVICEHEIGHTPOINTS=${heightPx}`,
'-dDPIx=300',
'-dDPIy=300',
`-sOutputFile=${outputFile}`,
inputFile,
].join(' ');
// 3. Test comando di sistema
const { exec } = require('child_process');
const util = require('util');
const execAsync = util.promisify(exec);
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!');
// Verifica che il file di output sia stato generato
if (tools.isFileExists(outputFile)) {
console.log('File di output generato:', outputFile);
} else {
console.error('Il File di output NON è stato generato! :', outputFile);
}
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) {
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}`);
} else {
throw new Error(`Errore durante la conversione: ${error.message}`);
}
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',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
'-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,
];
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 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);
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 };
}
async function ConvertPDF_Generatore(options, instampa) {
let fileout = '';
let fileout_compressed = '';
let suffisso_filename = '';
if (!options.filenameIn) {
return { err: 'Nessun file caricato.' };
return { err: 'Nessun file passato in Ingresso.' };
}
const outputFilename = path.basename(tools.removeFileExtension(options.filenameIn))+ '-stampabile.pdf';
const outputPath = path.join(options.dir_out, outputFilename);
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 });
await fs.promises.writeFile(outputPath, pdfBytes);
const dirUscita = path.dirname(outputFullPathFileName);
if (!(await tools.isDirectoryAsync(dirUscita))) {
await fs.promises.mkdir(dirUscita, { recursive: true });
}
fileout_print = outputPath;
await fs.promises.writeFile(outputFullPathFileName, pdfBytes);
fileout = outputFullPathFileName;
extractPdfInfo(fileout);
// 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);
}
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,72 +97,147 @@ 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 (isstream) {
// Se lo streaming è abilitato, restituiamo un flusso di dati
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
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 {
// Ottieni il flusso di dati da DeepSeek
const completionStream = await getDeepSeekResponse(prompt, options);
for await (const chunk of completionStream) {
if (chunk.choices && chunk.choices[0]) {
const data = JSON.stringify({ choice: chunk.choices[0] });
res.write(`data: ${data}\n\n`);
try {
const msg = chunk.choices[0].delta.content;
if (msg) {
console.log(msg);
// await tools.sleep(10000)
}
} catch (e) {
console.error('Error: ' + e.message);
}
}
}
// 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
}),
]);
res.write('data: [DONE]\n\n');
res.end();
let data = '';
let error = '';
} catch (error) {
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
console.error(errorstr);
// In caso di errore durante lo streaming, invia un messaggio di errore
const errorData = JSON.stringify({
code: server_constants.RIS_CODE_ERR,
error: errorstr,
ollama.stdout.on('data', (chunk) => {
data += chunk;
});
res.write(`data: ${errorData}\n\n`);
res.end();
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 {
try {
// Se lo streaming non è abilitato, restituisci la risposta completa
const choice = await getDeepSeekResponse(prompt, options);
const isstream = options && options?.stream;
return res.send({
code: server_constants.RIS_CODE_OK,
choice,
});
} catch (error) {
const errorstr = 'DeepSeek API Error:' + (error.response?.data || error.message)
console.error(errorstr);
if (isstream) {
// Se lo streaming è abilitato, restituiamo un flusso di dati
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// In caso di errore senza streaming, restituisci un errore standard
return res.send({
code: server_constants.RIS_CODE_ERR,
error: errorstr,
});
try {
// Ottieni il flusso di dati da DeepSeek
const completionStream = await getDeepSeekResponse(prompt, options);
for await (const chunk of completionStream) {
if (chunk.choices && chunk.choices[0]) {
const data = JSON.stringify({ choice: chunk.choices[0] });
res.write(`data: ${data}\n\n`);
try {
const msg = chunk.choices[0].delta.content;
if (msg) {
console.log(msg);
// await tools.sleep(10000)
}
} catch (e) {
console.error('Error: ' + e.message);
}
}
}
res.write('data: [DONE]\n\n');
res.end();
} catch (error) {
const errorstr = 'API Error:' + (error.response?.data || error.message);
console.error(errorstr);
// In caso di errore durante lo streaming, invia un messaggio di errore
const errorData = JSON.stringify({
code: server_constants.RIS_CODE_ERR,
error: errorstr,
});
res.write(`data: ${errorData}\n\n`);
res.end();
}
} else {
try {
// Se lo streaming non è abilitato, restituisci la risposta completa
const choice = await getDeepSeekResponse(prompt, options);
return res.send({
code: server_constants.RIS_CODE_OK,
choice,
});
} catch (error) {
const errorstr = 'API Error:' + (error.response?.data || error.message);
console.error(errorstr);
// In caso di errore senza streaming, restituisci un errore standard
return res.send({
code: server_constants.RIS_CODE_ERR,
error: errorstr,
});
}
}
}
});

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) {
if (status === shared_consts.OrderStatus.CHECKOUT_SENT) {
try {
const checkoutResult = await handleCheckout({
myorderCart,
mycart,
userId,
idapp,
req,
options,
userDest,
});
try {
const ris = await OrdersCart.updateOrdersCartById(-1, myorderCart);
// Gestisci il risultato qui
await Order.updateStatusOrders(mycart.items, status);
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
});
});
}
}
});
})
} catch (err) {
console.error("Errore durante l'aggiornamento dell'ordine:", err);
return res.send({ code: server_constants.RIS_CODE_ERR, status: 0 });
}
return res.send({
code: server_constants.RIS_CODE_OK,
status: checkoutResult.status,
orders: checkoutResult.orders,
recOrderCart: checkoutResult.recOrderCart,
});
} catch (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,24 +495,22 @@ 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
}
}
}
queryord.push(gasordine)
$type: 'objectId', // Checks if the field is of type ObjectId
$eq: new ObjectId(idGasordine), // Compares the value to a specific ObjectId
},
},
};
queryord.push(gasordine);
}
const query = [
{
$lookup: {
@@ -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,383 +692,359 @@ connectToDatabase(connectionUrl, options)
}
}
function getCredentials(hostname) {
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;
// Funzione migliorata per ottenere chiave e certificato
async function getCredentials(hostname) {
try {
let keyPath, certPath;
console.log('fileprivkey: ', fileprivkey, ' filecert: ', filecert);
/* return {
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"),
};
callback(null, domainCert);
} else {
callback(null, { key: privateKey, cert: certificate });
}
}
};*/
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
if (NUOVO_METODO_TEST) {
if (METODO_MULTI_CORS) {
// 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}`);
}
// 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}`);
}
// Leggi chiave e certificato
const key = fs.readFileSync(keyPath, 'utf8');
const cert = fs.readFileSync(certPath, '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)
};
} 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 };
// Metodo legacy (opzionale)
throw new Error('Metodo legacy non supportato');
}
} catch (error) {
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) {
function parseDomains() {
let domains = [];
let domainsAllowed = [];
try {
if (process.env.DOMAINS) domains = JSON.parse(process.env.DOMAINS);
if (process.env.DOMAINS_ALLOWED) domainsAllowed = JSON.parse(process.env.DOMAINS_ALLOWED);
} catch (error) {
console.error('Errore parsing DOMAINS:', error);
}
return { domains, domainsAllowed };
}
function buildAllowedOrigins(domains, domainsAllowed, isProduction) {
if (!isProduction) {
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}`,
`https://testapi.${domain.hostname}`,
`http://${domain.hostname}`,
`http://api.${domain.hostname}`,
`http://test.${domain.hostname}`,
`http://testapi.${domain.hostname}`,
]);
const allowedExtra = domainsAllowed.flatMap((domain) => [`https://${domain}`, `http://${domain}`]);
return [...baseOrigins, ...allowedExtra];
}
function createCorsOptions(domains, domainsAllowed, isProduction, noCors = false) {
if (noCors) {
console.log('NOCORS mode enabled');
return {
exposedHeaders: ['x-auth', 'x-refrtok'],
};
}
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',
'X-Requested-With',
'Content-Type',
'Accept',
'Authorization',
'x-auth',
'x-refrtok',
],
exposedHeaders: ['x-auth', 'x-refrtok'],
maxAge: 86400,
preflightContinue: false,
optionsSuccessStatus: 204,
};
}
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) => {
console.log(`${new Date().toISOString()} - ${req.method} ${req.url}`);
console.log('Request Headers:', req.headers);
const oldSend = res.send;
res.send = function (...args) {
console.log('Response Headers:', res.getHeaders());
return oldSend.apply(res, args);
};
next();
});
}
app.use((err, req, res, next) => {
if (err.message === 'CORS non permesso per questa origine') {
console.error('❌ Errore CORS:', {
origin: req.headers.origin,
method: req.method,
path: req.path,
});
return res.status(403).json({
error: `❌ CORS non permesso per questa origine (${req.headers.origin})`,
origin: req.headers.origin,
});
}
next(err);
});
}
async function createHttpOrHttpsServer(app, port, isProduction, domains) {
if (isProduction) {
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;
}
if (process.env.HTTPS_LOCALHOST === 'true') {
try {
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 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',
};
const httpsServer = https.createServer(credentials, app);
httpsServer.listen(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;
}
function setupWebSocketServer(httpOrHttpsServer) {
if (!httpOrHttpsServer) {
console.error('Nessun server HTTP o HTTPS disponibile per WebSocket');
return null;
}
const wss = new WebSocket.Server({ server: httpOrHttpsServer });
wss.on('connection', (ws) => {
console.log('Client socket connected...');
const { User } = require('./models/user');
const pty = require('node-pty');
let scriptProcess = null;
ws.on('message', async (message) => {
try {
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' }));
}
scriptProcess = pty.spawn('bash', [scriptPath], {
name: 'xterm-color',
cols: 80,
rows: 40,
cwd: process.cwd(),
env: process.env,
});
let buffer = '';
scriptProcess.on('data', (data) => {
buffer += data;
ws.send(JSON.stringify({ type: 'output', data }));
if (
buffer.endsWith(': ') ||
buffer.includes('? ') ||
buffer.toLowerCase().includes('password') ||
buffer.includes('Inserisci') ||
buffer.includes('Inserted') ||
buffer.includes('(Y)')
) {
ws.send(JSON.stringify({ type: 'input_required', prompt: data.trim() }));
buffer = '';
}
if (buffer.length > 5024) buffer = buffer.slice(-500);
});
scriptProcess.on('exit', (code) => {
const closeMsg = code === 0 ? '*** FINE SCRIPT ***' : `Script terminato con codice ${code}`;
ws.send(JSON.stringify({ type: 'close', data: closeMsg }));
});
} else if (parsed.type === 'input') {
if (scriptProcess) {
scriptProcess.write(parsed.data + '\n');
}
}
} catch (err) {
console.error("Errore durante l'elaborazione del messaggio:", err.message);
}
});
ws.on('close', () => {
console.log('*** Client socket disconnected');
if (scriptProcess) scriptProcess.kill();
});
});
return wss;
}
async function startServer(app, port) {
try {
const isProduction = ['production', 'test'].includes(process.env.NODE_ENV);
let domains = [];
let domains_allowed = [];
try {
if (process.env.DOMAINS) domains = JSON.parse(process.env.DOMAINS);
if (process.env.DOMAINS_ALLOWED) domains_allowed = JSON.parse(process.env.DOMAINS_ALLOWED);
} catch (error) {
console.error('Errore durante la conversione della stringa DOMAINS:', error);
}
console.log('domains', domains);
let httpsServer = null;
let httpServer = null;
console.log('isProduction', isProduction);
const ISDEBUG = false;
const NOCORS = false;
const ISDEBUG = false;
const { domains, domainsAllowed } = parseDomains();
let corsOptions = {};
console.log('domains:', domains);
console.log('isProduction:', isProduction);
if (NOCORS) {
console.log('NOCORS');
corsOptions = {
exposedHeaders: ['x-auth', 'x-refrtok'], // Intestazioni da esporre al client
};
} else {
console.log('WITH CORS');
let credentials = true;
const corsOptions = createCorsOptions(domains, domainsAllowed, isProduction, NOCORS);
let allowedOrigins = null;
setupMiddleware(app, corsOptions, ISDEBUG);
if (!isProduction) {
allowedOrigins = 'https://localhost:3000';
} else {
allowedOrigins = domains.flatMap((domain) => [
`https://${domain.hostname}`,
`https://api.${domain.hostname}`,
`https://test.${domain.hostname}`,
`https://testapi.${domain.hostname}`,
`http://${domain.hostname}`,
`http://api.${domain.hostname}`,
`http://test.${domain.hostname}`,
`http://testapi.${domain.hostname}`,
]);
const server = await createHttpOrHttpsServer(app, port, isProduction, domains);
// Aggiungi i domini da DOMAINS_ALLOWED
allowedOrigins = allowedOrigins.concat(
domains_allowed.map((domain) => [`https://${domain}`, `http://${domain}`]).flat()
);
}
const wss = setupWebSocketServer(server);
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);
}
};
}
// Configurazione CORS dettagliata
const corsOptions = {
origin: myorigin,
credentials,
methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
allowedHeaders: [
'Origin',
'X-Requested-With',
'Content-Type',
'Accept',
'Authorization',
'x-auth',
'x-refrtok',
],
exposedHeaders: ['x-auth', 'x-refrtok'],
maxAge: 86400, // Preflight cache 24 ore
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
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:', {
origin: req.headers.origin,
method: req.method,
path: req.path,
});
res.status(403).json({
error: '❌ CORS non permesso per questa origine (' + req.headers.origin + ')',
origin: req.headers.origin,
});
} else {
next(err);
}
});
}
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);
}
} 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 privateKey = fs.readFileSync(keyStream, 'utf8');
const certificate = fs.readFileSync(certificateStream, 'utf8');
mycredentials = {
key: privateKey,
cert: certificate,
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);
httpsServer.listen(port);
} else {
httpServer = http.createServer(app);
if (httpServer) {
console.log('⭐️⭐️⭐️ HTTP server IN LOCALE : port', port);
httpServer.listen(port);
}
}
// console.log('credentials', credentials);
} else {
httpServer = http.createServer(app);
if (httpServer) {
console.log('⭐️⭐️⭐️ HTTP server IN LOCALE : port', port);
httpServer.listen(port);
}
}
}
let wss = null;
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');
let scriptProcess = null;
const pty = require('node-pty');
ws.on('message', (message) => {
const parsedMessage = JSON.parse(message);
try {
if (parsedMessage.type === 'start_script' && User.isAdminById(parsedMessage.user_id)) {
if (scriptProcess) {
scriptProcess.kill();
}
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,
rows: 40,
cwd: process.cwd(),
env: process.env,
});
let buffer = '';
scriptProcess.on('data', (data) => {
buffer += 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.includes('? ') ||
buffer.toLowerCase().includes('password') ||
buffer.includes('Inserisci') ||
buffer.includes('Inserted') ||
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);
}
});
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}` }));
}
});
} else {
ws.send(JSON.stringify({ type: 'error', data: 'Script non trovato o non autorizzato' }));
}
} else if (parsedMessage.type === 'input') {
if (scriptProcess) {
scriptProcess.write(parsedMessage.data + '\n');
}
}
} catch (error) {
console.error("Errore durante l'elaborazione del messaggio:", error.message);
}
});
ws.on('close', () => {
console.log('*** Client socket disconnected');
if (scriptProcess) {
scriptProcess.kill();
}
});
});
} else {
console.error('Nessuna Socket Aperta con WebSocket !!');
}
} catch (e) {
console.log('error startServer: ' + e);
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==