const Importamacro = require('../models/importamacro'); // Assicurati di avere i modelli corretti const ImportaIsbn = require('../models/importaisbn'); const ProductInfo = require('../models/productInfo'); const Product = require('../models/product'); const CatProd = require('../models/catprod'); const SubCatProd = require('../models/subcatprod'); const Author = require('../models/author'); const Publisher = require('../models/publisher'); const Gasordine = require('../models/gasordine'); const tools = require('../tools/general'); // Assicurati di avere il file delle utility const shared_consts = require('../tools/shared_nodejs'); // Assicurati di avere le costanti condivise const { getTableContent } = require('../controllers/articleController'); class Macro { constructor(idapp, options) { this.idapp = idapp; this.localoptions = options; } async updateLocalDbFromGM_T_Web_Articoli(params) { let mylog = '' let numrec = 0; try { const options = { idapp: params.idapp, nameTable: 'T_Web_Articoli', campispeciali: true, recordraw: true, query: '', showQtaDisponibile: true, outhtml: false, cmd: shared_consts.CmdQueryMs.GET, inputdaGM: true, ...params, } let opt = { updated: 0, imported: 0, errors: 0, inputdaGM: options.inputdaGM, idapp: options.idapp, } let miomatch = {}; let miolimit = 0; if (options.caricatutti) { mylog = '*** CaricaTutti ***\n'; if (options.usaDBGMLocale) { mylog += '*** usaDBGMLocale ***\n'; miomatch = { IdStatoProdotto: { $in: [1, 4, 34, 45, 46] } }; // options.where = { IdStatoProdotto: { $in: [1, 4, 34, 45, 46] } }; } else { options.where = ` (DescrizioneStatoProdotto = 'In commercio' OR DescrizioneStatoProdotto = '2023 in commercio' OR DescrizioneStatoProdotto = 'Vendita sito' OR DescrizioneStatoProdotto = 'In prevendita' OR DescrizioneStatoProdotto = 'Prossima uscita') AND (DescrizioneTipologia = 'Libri') `; } } else { miolimit = 1; miomatch = { IdArticolo: Number(options.sku), Ean13: options.isbn, }; } if (options.usaDBGMLocale) { mylog += '*** usaDBGMLocale ***\n'; options.aggregation = [ { $match: miomatch }, { $sort: { DataOra: -1, }, }, { $group: { _id: "$IdArticolo", lastRecord: { $first: "$$ROOT" } // prendi il record più recente } }, { $replaceRoot: { newRoot: "$lastRecord" } }, ...(miolimit > 0 ? [{ $limit: miolimit }] : []), { $lookup: { from: 't_web_statiprodottos', localField: 'IdStatoProdotto', foreignField: 'IdStatoProdotto', as: 'StatoProdotto', } }, { $addFields: { DescrizioneStatoProdotto: { $arrayElemAt: ['$StatoProdotto.Descrizione', 0] }, } }, { $lookup: { from: 't_web_tipologies', localField: 'idTipologia', foreignField: 'idTipologia', as: 'DescrizioneTipologia', } }, { $addFields: { DescrizioneTipologia: { $arrayElemAt: ['$DescrizioneTipologia.Descrizione', 0] }, } }, { $lookup: { from: 't_web_tipiformatos', localField: 'idFormato', foreignField: 'idFormato', as: 'DescrizioneFormato', } }, { $addFields: { DescrizioneFormato: { $arrayElemAt: ['$DescrizioneFormato.Descrizione', 0] }, } }, { $lookup: { from: 't_web_collanes', localField: 'idCollana', foreignField: 'idCollana', as: 'DescrizioneCollana', } }, { $addFields: { DescrizioneCollana: { $arrayElemAt: ['$DescrizioneCollana.Descrizione', 0] }, } }, { $lookup: { from: 't_web_edizionis', localField: 'IdEdizione', foreignField: 'CodEdizione', as: 'editore', } }, { $addFields: { editore: { $arrayElemAt: ['$editore.Descrizione', 0] }, } }, { $addFields: { ListaAutoriArray: { $map: { input: { $split: ['$ListaAutori', ','] }, as: 'id', in: { $convert: { input: { $trim: { input: '$$id' } }, to: "int", onError: null, onNull: null } } } } } }, { $lookup: { from: 't_web_autoris', // assicurati che il nome della collezione sia corretto localField: 'ListaAutoriArray', foreignField: 'IdAutore', as: 'AutoriDettagliati' } }, { $addFields: { AutoriCompleti: { $reduce: { input: '$AutoriDettagliati', initialValue: '', in: { $cond: [ { $eq: ['$$value', ''] }, { $concat: ['$$this.Nome', ' ', '$$this.Cognome'] }, { $concat: ['$$value', ', ', '$$this.Nome', ' ', '$$this.Cognome'] } ] } } } } }, { $addFields: { ListaArgomentiArray: { $map: { input: { $split: ['$ListaArgomenti', ','] }, as: 'id', in: { $toInt: { $trim: { input: '$$id' } } } } } } }, // Step: Lookup verso collezione degli argomenti, ordinando per DataOra { $lookup: { from: 't_web_argomentis', let: { argomentiArray: '$ListaArgomentiArray' }, pipeline: [ { $match: { $expr: { $in: ['$IdArgomento', { $ifNull: ["$$argomentiArray", []] } ] } } }, { $sort: { DataOra: -1 } }, { $limit: 1 } ], as: 'ArgomentiDettagliati' } }, // Step: Genera campo DescrArgomento concatenando tutte le descrizioni { $addFields: { DescrArgomento: { $reduce: { input: '$ArgomentiDettagliati', initialValue: '', in: { $cond: [ { $eq: ['$$value', ''] }, '$$this.Descrizione', { $concat: ['$$value', ', ', '$$this.Descrizione'] } ] } } } } }, // Step: Pulisci i campi temporanei { $project: { ListaArgomentiArray: 0, // ArgomentiDettagliati: 0 } }, { $lookup: { from: 't_web_marchieditorialis', localField: 'IdMarchioEditoriale', foreignField: 'IdMarchioEditoriale', as: 'CasaEditrice', } }, { $addFields: { CasaEditrice: { $arrayElemAt: ['$CasaEditrice.Descrizione', 0] }, } }, ]; } else { if (!options.caricatutti) { // Singolo options.where = 'T.IdArticolo =' + options.sku + ' AND T.Ean13 = ' + options.isbn; } } const recproducts = await getTableContent(options); if (!tools.isArray(recproducts)) { console.error('Error: ', recproducts); mylog += recproducts + '\n'; } else { numrec = recproducts?.length || 0; console.log('numrec', numrec); } if (Array.isArray(recproducts)) { for (const recproduct of recproducts) { if (!options.caricatutti) { await this.elaboraProdotto(recproduct, opt); } } } mylog += ' *** IMPORTATI: ' + opt.imported + ' AGGIORNATI = ' + opt.updated + ' (su ' + numrec + ' RECORD)'; console.log(mylog); return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog }; } catch (e) { mylog += 'ERRORE ! *** IMPORTATI: ' + opt.imported + ' AGGIORNATI = ' + opt.updated + ' (su ' + numrec + ' RECORD)'; console.error(e.message); return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog }; } } /** * Funzione principale per importare il catalogo. */ async importaCatalogo(data) { let updated = 0, imported = 0, errors = 0; try { const ripopola = true; //++MODIFICARE! if (ripopola) { await this.pulisciECaricaDati(data); } const dataObjects = await Importamacro.find({ idapp: this.idapp }).lean(); console.log('*** INIZIO IMPORT PRODOTTI ... '); for (const product of dataObjects) { await this.elaboraProdotto(product, { updated, imported, errors }); } console.log( '*** IMPORTATI: ', imported, 'AGGIORNATI = ' + updated + ' (su ' + dataObjects.length + ' RECORD)' ); return { updated, imported, error }; } catch (e) { console.error(e.message); throw e; } } /** * Pulisce i dati esistenti e carica nuovi dati in Importamacro. */ async pulisciECaricaDati(data) { let dataObjects = null; try { dataObjects = JSON.parse(`[${data.arrdata}]`); } catch (e) { console.error('Errore nel parsing dei dati:', e); return; } if (dataObjects && dataObjects[0]) { await Importamacro.deleteMany({ idapp: this.idapp }); for (const recinv of dataObjects[0]) { const recmacro = this.preparaRecordMacro(recinv); const recrankingisbn = await ImportaIsbn.findOne({ sku: recmacro.sku }).lean(); if (recrankingisbn) { this.aggiornaCampiDaIsbn(recmacro, recrankingisbn); } try { await Importamacro.findOneAndUpdate( { idapp: this.idapp, _id: recmacro._id }, { $set: recmacro }, { new: true, upsert: true, strict: false } ); } catch (e) { console.error('Errore durante l\'inserimento:', e); } } } } /** * Prepara un record macro per l'inserimento. */ preparaRecordMacro(recinv) { const recmacro = { ...recinv }; recmacro.idapp = this.idapp; recmacro._id = recmacro.id; delete recmacro.id; return recmacro; } /** * Aggiorna i campi del record macro con i dati da ImportaIsbn. */ aggiornaCampiDaIsbn(recmacro, recrankingisbn) { if (!recmacro.isbn) recmacro.isbn = recrankingisbn.isbn; if ((!recmacro.Pagine || recmacro.Pagine === 0) && recrankingisbn.Pagine) recmacro.Pagine = recrankingisbn.Pagine; if (!recmacro.misure && recrankingisbn.misure) recmacro.misure = recrankingisbn.misure; } /** * Elabora un singolo prodotto. */ async elaboraProdotto(productInput, options) { let isnuovo = false, setta = false, importa = true; let product = { ...productInput }; if (options.inputdaGM) product = this.convertiDaCampiGMACampoFDV_ProductInfo(options.idapp, product); if (!product.title || !product.sku) importa = false; if (importa) { const productInfo = this.preparaProductInfo(product); if (this.localoptions?.importadaFDV) { const recrankingisbn = await ImportaIsbn.findOne({ sku: product.sku }).lean(); if (recrankingisbn) { this.aggiornaCampiDaIsbn(product, recrankingisbn); } } if (!product.hasOwnProperty('active')) { product.active = true; } await this.gestisciCategorie(productInfo, product); await this.gestisciAutori(productInfo, product); await this.gestisciEditore(productInfo, product); const risrecInfo = await ProductInfo.findOneAndUpdate( { code: productInfo.code }, { $set: productInfo }, { new: true, upsert: true } ); if (risrecInfo) { await this.aggiornaImmagineSeNecessario(risrecInfo); await this.gestisciGasOrdine(product, risrecInfo); await this.gestisciVariazioni(product, risrecInfo, options); } else { console.error('Errore ProductInfo:', product.code); options.errors++; } } } async gestisciGasOrdine(product) { // Cerca il GAS let recGas = null; if (product.gas_name) { // Cerca il GAS recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean(); } if (!recGas && !!product.gas_name) { recGas = new Gasordine({ idapp, name: product.gas_name, active: true }); // Non esiste questo GAS, quindi lo creo ! ris = await recGas.save(); recGas = await Gasordine.findOne({ idapp, name: product.gas_name }).lean(); } let recProductExist = null; let queryprod = { idProductInfo: product.idProductInfo }; if (recGas) { queryprod = { ...queryprod, idGasordine: recGas._id }; } recProductExist = await Product.findOne(queryprod).lean(); if (!recProductExist) { product.idGasordine = recGas ? recGas._id : null; await Product.findOneAndUpdate({ _id: product._id }, { $set: { idGasordine: product.idGasordine } }); } } preparaProductInfo(product) { try { return { idapp: product.idapp, code: product.isbn, id_wp: product._id || undefined, sku: product.sku, name: product.title, description: product.description, short_descr: product.short_descr, publisher: product.editore, collezione: product.Collezione, link: product.link || undefined, idCatProds: [], idSubCatProds: [], img2: product.img2 || undefined, img3: product.img3 || undefined, img4: product.img4 || undefined, checkout_link: product.checkout_link || undefined, idStatoProdotto: product.idStatoProdotto || undefined, date_pub: product.date_pub || undefined, sottotitolo: product.sottotitolo || undefined, }; } catch (e) { console.error('Errore preparaProductInfo :', e); return {}; } } getStatusByIdStatoProdotto(idStatoProdotto) { switch (idStatoProdotto) { case 1: case 4: case 34: case 45: case 46: return 'publish'; default: return 'out_of_stock'; } } convertiDaCampiGMACampoFDV_ProductInfo(idapp, productGM) { let productFDV = {}; /* productGM CAMPI { Id: "257825", IdArticolo: 20923, Ean13: "9788828508991", Titolo: "Fervìda: Fermenti di vita", ListaAutori: "3453", ListaArgomenti: "12", IdStatoProdotto: 46, PrezzoIvato: 13.9, IdMarchioEditoriale: 1, IdCollana: 175, DataPubblicazione: "2024-03-26T00:00:00.000Z", IdTipologia: 1, IdTipoFormato: 1, Misure: "cm 17x24", Pagine: "80", Sottotitolo: "", Durata: "", Numero: "", Edizione: "Marzo 2024", Ristampa: "", DataInizioCampagna: "2024-12-03T00:00:00.000Z", DataFineCampagna: "2099-12-31T00:00:00.000Z", ScontoCampagna: 5, PrezzoIvatoScontatoCampagna: 13.205, DataOra: "2024-12-03T09:56:21.540Z", Enabled: false, IDTagGruppo: 0, Utente: "LENOVO-I5", PercIva: 0, IdTitoloOriginale: 12272, EnabledAlFresco: true, CodEdizione: 0, FasciaEta: null, FasciaEta2: null, DescrizioneStatoProdotto: "In commercio", DescrizioneTipologia: "Libri", DescrizioneFormato: "Brossura", DescrizioneCollana: "Il Filo Verde di Arianna", AutoriCompleti: "Stefano Abbruzzese", DescrArgomento: "Autosufficienza, Autoproduzione e Vita Naturale", CasaEditrice: "MACRO EDIZIONI", } */ const recproduct = { idapp: idapp, isbn: productGM.Ean13, // id_wp: '', sku: productGM.IdArticolo, title: productGM.Titolo, // productInfo.name.replace(/ - Usato$| - Nuovo$| - Epub$| - Ebook$| - Mobi$| - DVD$| - Streaming$| - Download$/, ""); description: '', short_descr: '', editore: productGM.CasaEditrice, collezione: productGM.DescrizioneCollana, editore: productGM.CasaEditrice, Autore: productGM.AutoriCompleti, DescrArgomento: productGM.DescrArgomento, idStatoProdotto: productGM.IdStatoProdotto, Stato: this.getStatusByIdStatoProdotto(productGM.IdStatoProdotto), price: productGM.PrezzoIvato, sale_price: productGM.PrezzoIvatoScontatoCampagna, formato: productGM.DescrizioneFormato, Tipologia: productGM.DescrizioneTipologia, Edizione: productGM.Edizione, Pagine: productGM.Pagine, misure: productGM.Misure, eta: productGM.FasciaEta, // addtocart_link: '', Quantita: productGM.QtaDisponibile || undefined, date_pub: tools.getDateFromISOString(productGM.DataPubblicazione), sottotitolo: productGM.Sottotitolo, productTypes: [shared_consts.PRODUCTTYPE.PRODUCT], } let vers = 0; if (productGM.DescrizioneTipologia === 'Usato') vers = shared_consts.PRODUCTTYPE.USATO; else if (productGM.DescrizioneTipologia === 'Download') vers = shared_consts.PRODUCTTYPE.DOWNLOAD; else if (productGM.DescrizioneTipologia === 'DVD') vers = shared_consts.PRODUCTTYPE.DVD; else if (productGM.DescrizioneTipologia === 'Epub') vers = shared_consts.PRODUCTTYPE.EPUB; else if (productGM.DescrizioneTipologia === 'Mobi') vers = shared_consts.PRODUCTTYPE.MOBI; else if (productGM.DescrizioneTipologia === 'PDF') vers = shared_consts.PRODUCTTYPE.PDF; else if (productGM.DescrizioneTipologia === 'Streaming') vers = shared_consts.PRODUCTTYPE.STREAMING; else vers = shared_consts.PRODUCTTYPE.NUOVO; recproduct.Versione = vers; return recproduct } /** * Gestisce le categorie e sottocategorie del prodotto. */ async gestisciCategorie(productInfo, product) { if (product.DescrArgomento) { productInfo.idCatProds = []; const reccateg = await CatProd.findOne({ idapp: this.idapp, name: product.DescrArgomento }).lean(); let nuovaCategoria = null; if (!reccateg) { nuovaCategoria = new CatProd({ idapp: this.idapp, name: product.DescrArgomento }); await nuovaCategoria.save(); } const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null) if (myriscat) productInfo.idCatProds.push(myriscat); } else { if (product.categories) { // const arrcat = product.categories.trim().split(','); const arrcat = product.categories.trim().split(','); productInfo.idCatProds = []; for (const mycat of arrcat) { const mycatstr = mycat.trim(); const reccateg = await CatProd.findOne({ idapp: this.idapp, name: mycatstr }).lean(); let nuovaCategoria = null; if (!reccateg) { nuovaCategoria = new CatProd({ idapp: this.idapp, name: mycatstr }); await nuovaCategoria.save(); } const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null) if (myriscat) productInfo.idCatProds.push(myriscat); } } } } /** * Gestisce gli autori del prodotto. */ async gestisciAutori(productInfo, product) { if (product.Autore) { let arrAuthor = [] if (product.id_wp) arrAuthor = this.estraiAutori_FDV(product.Autore); else arrAuthor = this.estraiAutori(product.Autore); productInfo.idAuthors = []; for (const author of arrAuthor) { const recauthor = await Author.findOne({ idapp: this.idapp, name: author.name, surname: author.surname }).lean(); let nuovoAutore = null; if (!recauthor) { nuovoAutore = new Author({ idapp: this.idapp, name: author.name, surname: author.surname }); await nuovoAutore.save(); } const myrisautore = recauthor?._id || (nuovoAutore ? nuovoAutore._id : ''); if (myrisautore) productInfo.idAuthors.push(myrisautore); } } } estraiAutori(autoreString) { const arrrecauthor = autoreString.trim().split(','); const arrAuthor = []; for (let i = 0; i < arrrecauthor.length; i += 2) { const nomecognome = arrrecauthor[i].trim(); let arrrecns = nomecognome.trim().split(' '); let name = ''; let surname = ''; if (arrrecns && arrrecns.length === 4) { name = arrrecns[0].trim() + ' ' + arrrecns[1].trim(); surname = arrrecns[2].trim() + ' ' + arrrecns[3].trim();; } else { if (arrrecns && arrrecns.length === 1) { name = arrrecns[0].trim(); } else { name = arrrecns[0].trim(); surname = arrrecns.slice(1).join(' ').trim(); } } arrAuthor.push({ name, surname }); } return arrAuthor; } /** * Estrae gli autori dal campo "Autore". */ estraiAutori_FDV(autoreString) { const arrrecauthor = autoreString.trim().split(','); const arrAuthor = []; for (let i = 0; i < arrrecauthor.length; i += 2) { const name = arrrecauthor[i].trim(); const surname = arrrecauthor[i + 1]?.trim() || ''; arrAuthor.push({ name, surname }); } return arrAuthor; } /** * Gestisce l'editore del prodotto. */ async gestisciEditore(productInfo, product) { if (productInfo.publisher) { const publisher = productInfo.publisher.trim(); const recpublisher = await Publisher.findOne({ idapp: this.idapp, name: publisher }).lean(); if (!recpublisher) { const nuovoEditore = new Publisher({ idapp: this.idapp, name: publisher }); await nuovoEditore.save(); } productInfo.idPublisher = recpublisher?._id || nuovoEditore._id; } } /** * Aggiorna l'immagine se necessario. */ async aggiornaImmagineSeNecessario(productInfo) { const { prodInfo, aggiornatoimg } = await tools.downloadImgIfMissing(productInfo); if (aggiornatoimg) { await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: prodInfo }); } } /** * Prepara una variazione del prodotto. */ preparaVariazione(product) { return { active: true, versione: product.Versione, status: product.Stato || null, price: product.price ? parseFloat(tools.convertPriceEurToValue(product.price)) : null, sale_price: product.sale_price ? parseFloat(tools.convertPriceEurToValue(product.sale_price)) : null, formato: product.formato || '', tipologia: product.Tipologia || '', edizione: product.Edizione || '', pagine: tools.isValidNumber(product.Pagine) ? tools.convstrToInt(product.Pagine) : 0, misure: product.misure || '', eta: product.eta || '', addtocart_link: product.addtocart_link || '', quantita: product.Quantita ? parseInt(product.Quantita) : 0, preOrderDate: product.preOrderDate || null, }; } /** * Aggiorna l'array delle variazioni. */ aggiornaVariazioni(arrvariazioni, nuovaVariazione) { const ind = arrvariazioni.findIndex((x) => x.versione === nuovaVariazione.versione); if (ind >= 0) { arrvariazioni[ind] = nuovaVariazione; } else { arrvariazioni.push(nuovaVariazione); } return arrvariazioni.sort((a, b) => a.versione - b.versione); } /** * Gestisce le variazioni del prodotto. */ async gestisciVariazioni(product, risrecInfo, options) { const queryprod = { idProductInfo: risrecInfo._id }; const recold = await Product.findOne(queryprod).lean(); const variazione = this.preparaVariazione(product); let risultupdate = null; if (recold) { const arrvariazioni = this.aggiornaVariazioni(recold.arrvariazioni, variazione); risultupdate = await Product.findOneAndUpdate(queryprod, { $set: { arrvariazioni } }); options.updated++; } else { const myproduct = { ...queryprod, arrvariazioni: [variazione] }; risultupdate = await Product.findOneAndUpdate(queryprod, { $set: myproduct }, { new: true, upsert: true }); options.imported++; } // console.log('risultupdate', risultupdate); } } module.exports = Macro;