- Ricerca Titolo per nome o autore o ISBN o codice articolo

This commit is contained in:
Surya Paolo
2025-03-31 23:56:01 +02:00
parent 789dc1dcae
commit 5431fe118e
9 changed files with 345 additions and 114 deletions

View File

@@ -243,7 +243,7 @@ const getTableContent = async (options) => {
}
// Esegue la query per recuperare i dati
console.log('dataQuery', dataQuery);
// console.log('dataQuery', dataQuery);
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
headers: { 'x-api-key': API_KEY }
});

View File

@@ -29,7 +29,8 @@ const CatalogSchema = new Schema({
},
foto_collana: IImg,
idCollane: [{
type: Number,
type: Schema.Types.ObjectId,
ref: 'Collana',
}],
argomenti: [{
type: String,
@@ -72,6 +73,10 @@ const CatalogSchema = new Schema({
date_updated: {
type: Date,
},
lista_prodotti: [{
type: Schema.Types.ObjectId,
ref: 'Product',
}],
});
/*
@@ -94,7 +99,7 @@ CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
return tools.executeQueryTable(this, idapp, params, user);
};
CatalogSchema.statics.findAllIdApp = async function (idapp) {
CatalogSchema.statics.OLD_findAllIdApp = async function (idapp) {
const Catalog = this;
const arrrec = await Catalog.aggregate([
@@ -119,6 +124,94 @@ CatalogSchema.statics.findAllIdApp = async function (idapp) {
return arrrec;
};
CatalogSchema.statics.findAllIdApp = async function (idapp) {
const Catalog = this;
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
})
.populate({
path: "lista_prodotti", // Popola il campo lista_prodotti
populate: {
path: "idProductInfo", // Popola il campo idProductInfo dentro ogni prodotto
model: "ProductInfo", // Specifica il modello della collezione ProductInfo
populate: [
{
path: "idCatProds",
model: "CatProd"
},
{
path: "idSubCatProds",
model: "SubCatProd"
},
{
path: "idAuthors",
model: "Author"
}
],
},
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProducer",
model: "Producer"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProvider",
model: "Provider"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idStorehouses",
model: "Storehouse"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idScontisticas",
model: "Scontistica"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idGasordine",
model: "Gasordine"
}
})
;
const transformedArrRec = arrrec.map(catalog => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
...product.toObject(),
productInfo: {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo
catprods: product.idProductInfo.idCatProds, // Rinomina idCatProds in catprods
subcatprods: product.idProductInfo.idSubCatProds,
collana: product.idProductInfo.idCollana,
authors: product.idProductInfo.idAuthors,
},
producer: product.idProducer,
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
})),
}));
return transformedArrRec;
};
const Catalog = mongoose.model('Catalog', CatalogSchema);
Catalog.createIndexes()

View File

@@ -56,6 +56,7 @@ const IDimensioni = new Schema({
});
const IPagina = new Schema({
dimensioni: IDimensioni,
testo_title: IText,
testo_up: IText,
testo_down: IText,
});

View File

@@ -254,56 +254,45 @@ module.exports.executeQueryPickup = async function (idapp, params) {
filterfindexact = { comune: strfind };
}
let limit = 10;
let limit = 20;
let risexact = [];
let filterfind = {
idapp,
$or: [
{
'productInfo.name': {
$regex: `\\b${strfind}`, // Usa \\b per trovare solo le parole che iniziano con strfind
$options: 'i' // Rendi la ricerca case-insensitive
$regex: `\\b${strfind}`, // Cerca parole che iniziano con strfind
$options: 'i' // Rende la ricerca case-insensitive
}
},
{
'productInfo.code': {
$regex: `\\b${strfind}`, // Cerca parole che iniziano con strfind
$options: 'i' // Rende la ricerca case-insensitive
}
},
{
'productInfo.sku': {
$regex: `\\b${strfind}`, // Cerca parole che iniziano con strfind
$options: 'i' // Rende la ricerca case-insensitive
}
},
{
'productInfo.authors.name': {
$regex: `\\b${strfind}`, // Cerca parole che iniziano con strfind nel nome dell'autore
$options: 'i' // Rende la ricerca case-insensitive
}
},
{
'productInfo.authors.surname': {
$regex: `\\b${strfind}`, // Cerca parole che iniziano con strfind nel cognome dell'autore
$options: 'i' // Rende la ricerca case-insensitive
}
},
]
};
/*
let aggr1 = [
{
$lookup: {
from: 'productinfos',
localField: 'idProductInfo',
foreignField: '_id',
as: 'productInfo'
}
},
{
$lookup: {
from: 'authors',
localField: 'idAuthors',
foreignField: '_id',
as: 'authors'
}
},
{
$match: { 'productInfo.name': strfind },
},
{ $limit: 1 },
{
$project: {
name: { $concat: ["$productInfo.name", " (", "$authors", ")"] },
},
},
];
if (params.filter) {
filterfind = { ...params.filter, ...filterfind };
limit = 200;
} else {
// risexact = await City.find(filterfindexact, {comune: 1, prov: 1, reg: 1}).lean();
risexact = await City.aggregate(aggr1);
}
*/
if (params.filter) {
filterfind = { ...params.filter, ...filterfind };
limit = 200;
@@ -327,24 +316,34 @@ module.exports.executeQueryPickup = async function (idapp, params) {
{
$lookup: {
from: 'authors',
localField: 'idAuthors',
localField: 'productInfo.idAuthors',
foreignField: '_id',
as: 'authors'
as: 'productInfo.authors'
}
},
{
$unwind: {
path: '$authors',
preserveNullAndEmptyArrays: true,
},
},
{
$match: filterfind,
},
{ $limit: limit },
{
$project: {
name: '$productInfo.name',
},
name: '$productInfo.name', // Nome del prodotto
authors: '$productInfo.authors',
productInfo: {
name: '$productInfo.name', // Nome del prodotto
authors: '$productInfo.authors',
},
}
}
];
// let ris = await City.find(filterfind, {comune: 1, prov: 1, reg: 1}).lean().limit(limit);
let ris = await this.aggregate(aggr2).limit(limit);
return [...risexact, ...ris];

View File

@@ -115,16 +115,19 @@ async function findOrCreateCatProd(idapp, idArgomento, DescrArgomento) {
function updateProductInfoCatProds(productInfo, reccatprod) {
if (productInfo) {
const isChanged = (!productInfo.idCatProds || productInfo.idCatProds.length < 1) ||
(productInfo.idCatProds[0].toString() !== reccatprod._id.toString());
// Controllo che nell'array productInfo.idCatProds ci sia esattamente 1 record e che sia uguale a reccatprod._id
const cond3 = Array.isArray(productInfo.idCatProds) && productInfo.idCatProds[0].toString() !== reccatprod._id.toString();
const isChanged =
!Array.isArray(productInfo.idCatProds) || // Assicurati che sia un array
productInfo.idCatProds.length !== 1 || // L'array deve contenere esattamente 1 elemento
cond3; // Il primo elemento deve essere uguale a reccatprod._id
if (isChanged) {
productInfo.idCatProds = [reccatprod._id];
console.log('ARGOMENTO VARIATO!', reccatprod.name);
console.log('ARGOMENTO VARIATO!', reccatprod.name, ' Libro:', productInfo.name);
}
}
}
async function compressPdf(inputFile, outputFile, compressione) {
try {
const tempFolder = path.join(cwd, "temp");
@@ -406,11 +409,20 @@ function fixURL(url) {
async function downloadImgIfMissing(productInfo) {
if (!productInfo.image_link)
return { prodInfo: null, aggiornatoimg: false };
try {
if (tools.sulServer()) {
dirmain = '';
} else {
dirmain = server_constants.DIR_PUBLIC_LOCALE;
}
const vecchiomodo = false;
if (productInfo.image_link && vecchiomodo) {
const relativeimg = productInfo.image_link.split('/').pop();
const img = 'upload/products/' + productInfo.image_link.split('/').pop();
const img = tools.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.image_link.split('/').pop();
const savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
let scaricaimg = !productInfo.imagefile || !fs.existsSync(savePath);
@@ -437,7 +449,8 @@ async function downloadImgIfMissing(productInfo) {
}
}
if (scaricaimg) {
if (scaricaimg && vecchiomodo) {
// Download image from the URL productInfo.image_link
productInfo.imagefile = relativeimg;
@@ -458,11 +471,76 @@ async function downloadImgIfMissing(productInfo) {
return result;
});
return { prodInfo: productInfo, aggiornatoimg };
return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris };
}
}
let fileesistente = false;
if (productInfo.imagefile) {
// controlla se esiste il file
const img = tools.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop();
const filecompleto = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
// Se non esiste lo scarico !
fileesistente = fs.existsSync(filecompleto);
}
if (!vecchiomodo && (!productInfo.image_link || !fileesistente)) {
let scarica_da_sito = !productInfo.imagefile;
if (!scarica_da_sito && productInfo.imagefile) {
scarica_da_sito = !fileesistente; // Se non esiste lo scarico !
}
if (scarica_da_sito) {
// date and time
productInfo.imagefile = 'img_' + new Date().toISOString().replace(/T/, ' ').replace(/\..+/, '');
const img = tools.getdirByIdApp(productInfo.idapp) + dirmain +
server_constants.DIR_UPLOAD + '/products/' + productInfo.imagefile.split('/').pop();
let savePath = path.resolve(__dirname, img); // Sostituisci con il percorso dove salvare l'immagine
let link = 'https://www.gruppomacro.com/copertine.php?id_gm=' + productInfo.sku
const downloader = new ImageDownloader();
const aggiornatoimg = await downloader.downloadImage(link, savePath,
{
maxRetries: 3,
initialDelay: 300,
timeout: 15000,
nomefileoriginale: true,
}).then(result => {
if (result) {
// console.log('Download completato con successo!');
} else {
console.log('Download non riuscito.');
}
return result;
});
if (aggiornatoimg.filepath) {
const filenamebase = path.basename(aggiornatoimg.filepath);
// const img = '/upload/products/' + filenamebase;
productInfo.imagefile = filenamebase;
}
return { prodInfo: productInfo, aggiornatoimg: aggiornatoimg.ris };
} else {
return { prodInfo: null, aggiornatoimg: false };
}
}
} catch (e) {
console.error('downloadImgIfMissing', e.message);
}
return { prodInfo: null, aggiornatoimg: false };
}
async function completaSettaggioProduct_AndProductInfo(arrcampi_productInfo, arrcampi_product, rec, product, productInfo) {
@@ -1042,8 +1120,7 @@ router.post('/import', authenticate, async (req, res) => {
let imported = 0;
let errors = 0;
const ripopola = true;
const ripopola = false; //++MODIFICARE!
if (ripopola) {
dataObjects = null;
@@ -1131,6 +1208,8 @@ router.post('/import', authenticate, async (req, res) => {
let importa = true;
if (!product.title || !product.sku)
importa = false;
@@ -1145,10 +1224,13 @@ router.post('/import', authenticate, async (req, res) => {
if (!product.isbn) {
const rectrovare = await ImportaIsbn.findOne({ sku: product.sku }).lean();
if (rectrovare) {
// se l'isbn non inizia con 'field' allora è buono
if (rectrovare.isbn && !rectrovare.isbn.startsWith('field')) {
product.isbn = rectrovare.isbn;
}
} else {
nontrovati++;
console.log(`${nontrovati} - ISBN non trovato [sku=${product.sku} title=${product.title}]`)
// console.log(`${nontrovati} - ISBN non trovato [sku=${product.sku} title=${product.title}]`)
}
}
@@ -1169,12 +1251,21 @@ router.post('/import', authenticate, async (req, res) => {
idCatProds: [],
idSubCatProds: [],
//img: 'upload/products/' + product.code + '.jpg',
image_link: product.image_link ? product.image_link : '',
// image_link: product.image_link ? product.image_link : '',
img2: product.img2 ? product.img2 : '',
img3: product.img3 ? product.img3 : '',
img4: product.img4 ? product.img4 : '',
checkout_link: product.checkout_link ? product.checkout_link : '',
}
const test = false;
if (test) {
productInfo.imagefile = ''
productInfo.image_link = '';
let { prodInfo, aggiornatoimg } = await downloadImgIfMissing(productInfo);
console.log('imagefile=', prodInfo.imagefile)
}
let esisteindb = await ProductInfo.findOne({ code: productInfo.code }).lean();
if (esisteindb) {
@@ -1250,6 +1341,7 @@ router.post('/import', authenticate, async (req, res) => {
} else {
arrcat = product.categories.trim().split(',');
productInfo.idCatProds = [];
for (const mycat of arrcat) {
let mycatstr = mycat.trim();
@@ -1336,6 +1428,7 @@ router.post('/import', authenticate, async (req, res) => {
if (product.subcat_name) {
arrsubcat = product.subcat_name.trim().split(',');
productInfo.idSubCatProds = [];
for (const mysubcat of arrsubcat) {
let mysubcatstr = mysubcat.trim();
@@ -1662,6 +1755,7 @@ router.post('/import', authenticate, async (req, res) => {
if (product.subcat_name) {
arrsubcat = product.subcat_name.trim().split(',');
productInfo.idSubCatProds = [];
for (const mysubcat of arrsubcat) {
let mysubcatstr = mysubcat.trim();

View File

@@ -2304,7 +2304,7 @@ function uploadFile(req, res, version) {
if (tools.sulServer()) {
dirmain = '';
} else {
dirmain = '/public';
dirmain = server_constants.DIR_PUBLIC_LOCALE;
}
}
@@ -2503,7 +2503,7 @@ function deleteFile(req, res, version) {
let dirmain = '';
if (version > 0) {
if (!tools.sulServer()) {
dirmain = '/public';
dirmain = server_constants.DIR_PUBLIC_LOCALE;
}
}

View File

@@ -540,7 +540,7 @@ connectToDatabase(connectionUrl, options)
try {
if (!tools.sulServer()) {
dirmain = '/public';
dirmain = server_constants.DIR_PUBLIC_LOCALE;
}
for (const rec of arrlist) {

View File

@@ -433,7 +433,8 @@ class ImageDownloader {
initialDelay = 1000, // Ritardo iniziale
maxDelay = 10000, // Ritardo massimo
timeout = 30000, // Timeout della richiesta
validateContentType = true // Verifica del tipo di contenuto
validateContentType = true, // Verifica del tipo di contenuto
nomefileoriginale = true,
} = options;
// Funzione per il backoff esponenziale
@@ -448,7 +449,6 @@ class ImageDownloader {
fs.unlinkSync(filepath);
}
const writer = fs.createWriteStream(filepath);
if (attempt > 1)
console.log(`📥 Tentativo ${attempt}/${maxRetries} - Scaricamento: ${url}`);
@@ -487,6 +487,28 @@ class ImageDownloader {
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) => {
@@ -501,8 +523,11 @@ class ImageDownloader {
});
});
console.info(`✅ Immagine scaricata con successo in ${filepath}`);
return true;
return { ris: true, filepath };
} catch (error) {
console.error(`❌ Errore nel tentativo ${attempt}/${maxRetries}:`, error.message);
@@ -514,7 +539,7 @@ class ImageDownloader {
if (attempt === maxRetries) {
console.error(`Download fallito dopo ${maxRetries} tentativi: ${error.message}`);
return false;
return { ris: false };
}
const delay = getDelay(attempt);
@@ -523,6 +548,24 @@ class ImageDownloader {
}
}
}
// 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;
}
}

View File

@@ -101,6 +101,7 @@ module.exports = Object.freeze({
PREFIX_IMG_SMALL: 'sm_',
DIR_UPLOAD: '/upload', //'/upload'
DIR_PUBLIC_LOCALE: '/public',
Privacy: {
all: 'all',