1175 lines
37 KiB
JavaScript
1175 lines
37 KiB
JavaScript
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 Collana = require('../models/collana');
|
|
const Gasordine = require('../models/gasordine');
|
|
const tools = require('../tools/general'); // Assicurati di avere il file delle utility
|
|
const shared_consts = require('../tools/shared_nodejs'); // Assicurati di avere le costanti condivise
|
|
|
|
const Storehouse = require('../models/storehouse');
|
|
const { getTableContent } = require('../controllers/articleController');
|
|
|
|
const T_WEB_ArticoliFatturati = require('../models/t_web_articolifatturati');
|
|
const T_WEB_Ordini = require('../models/t_web_ordini');
|
|
const T_Web_Argomenti = require('../models/t_web_argomenti');
|
|
const { JobsInProgress } = require('../models/JobsInProgress');
|
|
|
|
class Macro {
|
|
constructor(idapp, options) {
|
|
this.idapp = idapp;
|
|
this.localoptions = options;
|
|
this.recProductExist = false;
|
|
this.queryprod = null;
|
|
}
|
|
|
|
async updateLocalDbFromGM_T_Web_Articoli(params) {
|
|
console.log('INIZIO updateLocalDbFromGM_T_Web_Articoli...', params);
|
|
|
|
let mylog = '';
|
|
let numrec = 0;
|
|
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 myjob = null;
|
|
|
|
const lavoromassivo = options.caricatutti;
|
|
if (lavoromassivo) {
|
|
myjob = await JobsInProgress.addNewJob({
|
|
idapp: options.idapp,
|
|
descr: 'Riaggiorna Articoli',
|
|
nomeFunzioneDbOp: 'updateAllBook',
|
|
status: shared_consts.STATUS_JOB.START,
|
|
});
|
|
if (!myjob) {
|
|
mylog = 'ATTENZIONE! ❌ STAVO GIA ESEGUENDO QUESTO JOB, quindi ESCO !';
|
|
console.error(mylog);
|
|
return {
|
|
updated: opt.updated,
|
|
imported: opt.imported,
|
|
errors: opt.errors,
|
|
mylog,
|
|
idRecUpdated: opt.idRecUpdated,
|
|
table: opt.table,
|
|
};
|
|
}
|
|
}
|
|
|
|
try {
|
|
let miomatch = {};
|
|
let miomatch2 = {};
|
|
let miolimit = 0;
|
|
|
|
if (options.caricatutti) {
|
|
mylog = '*** CaricaTutti ***\n';
|
|
|
|
if (options.usaDBGMLocale) {
|
|
mylog += '*** usaDBGMLocale ***\n';
|
|
//miomatch2 = { IdStatoProdotto: { $in: [1, 4, 34, 45, 46] } };
|
|
|
|
miomatch2 = {
|
|
$or: [
|
|
{ DescrizioneStatoProdotto: 'In commercio' },
|
|
{ DescrizioneStatoProdotto: 'Prossima uscita/pubblicazione' },
|
|
{ DescrizioneStatoProdotto: 'Prossima uscita' },
|
|
{ DescrizioneStatoProdotto: 'In prevendita' },
|
|
{ DescrizioneStatoProdotto: 'Vendita sito' },
|
|
{ DescrizioneStatoProdotto: '2023 in commercio' },
|
|
],
|
|
Ean13: { $not: /^USATO/ },
|
|
};
|
|
|
|
/*
|
|
1 In commercio
|
|
3 Ristampa
|
|
4 Prossima uscita/pubblicazione
|
|
6 In promozione
|
|
7 In fase di valutazione
|
|
8 Titolo in esaurimento (in attesa Nuova Edizione)
|
|
9 Titolo in esaurimento
|
|
20 Titolo in esaurimento (in att N.E Ricopertinata)
|
|
26 Titolo in Esaurimento (disponibile N.E.)
|
|
33 In commercio (digitale)
|
|
34 In prevendita
|
|
45 Vendita sito
|
|
46 2023 in commercio
|
|
47 Assoluto NO Reso
|
|
48 Titolo esaurito
|
|
|
|
*/
|
|
|
|
// options.where = { IdStatoProdotto: { $in: [1, 4, 34, 45, 46] } };
|
|
} else {
|
|
options.where = `
|
|
(DescrizioneStatoProdotto = 'In commercio' OR
|
|
DescrizioneStatoProdotto = 'Prossima uscita/pubblicazione' OR
|
|
DescrizioneStatoProdotto = 'Prossima uscita' OR
|
|
DescrizioneStatoProdotto = 'In prevendita' OR
|
|
DescrizioneStatoProdotto = '2023 in commercio')
|
|
AND
|
|
(DescrizioneTipologia = 'Libri' OR
|
|
DescrizioneTipologia = 'Cartolibro' OR
|
|
DescrizioneTipologia = 'Carte')
|
|
AND
|
|
(Ean13 NOT LIKE 'USATO%')
|
|
`;
|
|
}
|
|
} else {
|
|
miolimit = 1;
|
|
miomatch = {
|
|
IdArticolo: Number(options.sku),
|
|
Ean13: options.isbn,
|
|
};
|
|
}
|
|
|
|
let filtroTipologia = null;
|
|
|
|
// FILTRO PER LIBRI
|
|
if (true) {
|
|
filtroTipologia = {
|
|
$match: {
|
|
DescrizioneTipologia: { $in: ['Libri', 'Cartolibro', 'Carte'] },
|
|
},
|
|
};
|
|
}
|
|
|
|
if (options.usaDBGMLocale) {
|
|
mylog += '*** usaDBGMLocale ***\n';
|
|
options.aggregation = [
|
|
{
|
|
$match: {
|
|
...miomatch,
|
|
},
|
|
},
|
|
{
|
|
$sort: {
|
|
DataOra: -1,
|
|
},
|
|
},
|
|
{
|
|
$group: {
|
|
_id: '$IdArticolo',
|
|
lastRecord: { $first: '$$ROOT' },
|
|
},
|
|
},
|
|
{
|
|
$replaceRoot: { newRoot: '$lastRecord' },
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: 't_web_statiprodottos',
|
|
localField: 'IdStatoProdotto',
|
|
foreignField: 'IdStatoProdotto',
|
|
as: 'StatoProdotto',
|
|
pipeline: [
|
|
{
|
|
$sort: { DataOra: -1 },
|
|
},
|
|
{
|
|
$limit: 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
DescrizioneStatoProdotto: { $arrayElemAt: ['$StatoProdotto.Descrizione', 0] },
|
|
},
|
|
},
|
|
{
|
|
$match: {
|
|
...miomatch2,
|
|
},
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: 't_web_tipologies',
|
|
localField: 'IdTipologia',
|
|
foreignField: 'IdTipologia',
|
|
as: 'DescrizioneTipologia',
|
|
pipeline: [
|
|
{
|
|
$sort: { DataOra: -1 },
|
|
},
|
|
{
|
|
$limit: 1,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
DescrizioneTipologia: { $arrayElemAt: ['$DescrizioneTipologia.Descrizione', 0] },
|
|
},
|
|
},
|
|
{
|
|
$match: {
|
|
$expr: {
|
|
$in: ['$DescrizioneTipologia', ['Libri', 'Cartolibro']],
|
|
},
|
|
},
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: 't_web_tipiformatos',
|
|
localField: 'IdTipoFormato',
|
|
foreignField: 'IdTipoFormato',
|
|
as: 'DescrizioneFormato',
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
DescrizioneFormato: { $arrayElemAt: ['$DescrizioneFormato.Descrizione', 0] },
|
|
},
|
|
},
|
|
...(filtroTipologia ? [filtroTipologia] : []),
|
|
{
|
|
$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'] },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
$project: {
|
|
ListaAutoriArray: 0,
|
|
AutoriDettagliati: 0,
|
|
},
|
|
},
|
|
{
|
|
$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 },
|
|
{ $project: { Descrizione: 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'] },
|
|
],
|
|
},
|
|
},
|
|
},
|
|
},
|
|
},
|
|
{
|
|
$project: {
|
|
ArgomentiDettagliati: 0,
|
|
ListaArgomentiArray: 0,
|
|
},
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: 't_web_disponibiles',
|
|
let: { codice: { $toString: '$IdArticolo' } },
|
|
pipeline: [
|
|
{ $match: { $expr: { $eq: ['$Codice', '$$codice'] } } },
|
|
{ $sort: { DataOra: -1 } },
|
|
{ $limit: 1 },
|
|
{ $project: { QtaDisponibile: 1 } },
|
|
],
|
|
as: 'DisponibileDettaglio',
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
QtaDisponibile: { $arrayElemAt: ['$DisponibileDettaglio.QtaDisponibile', 0] },
|
|
},
|
|
},
|
|
// Step: Pulisci i campi temporanei
|
|
{
|
|
$project: {
|
|
DisponibileDettaglio: 0,
|
|
},
|
|
},
|
|
{
|
|
$lookup: {
|
|
from: 't_web_marchieditorialis',
|
|
localField: 'IdMarchioEditoriale',
|
|
foreignField: 'IdMarchioEditoriale',
|
|
as: 'CasaEditrice',
|
|
},
|
|
},
|
|
{
|
|
$addFields: {
|
|
CasaEditrice: { $arrayElemAt: ['$CasaEditrice.Descrizione', 0] },
|
|
},
|
|
},
|
|
];
|
|
} else {
|
|
if (!options.caricatutti) {
|
|
if (options.sku) {
|
|
options.where = 'T.IdArticolo =' + options.sku + " AND T.Ean13 = '" + options.isbn + "'";
|
|
} else {
|
|
options.where = "T.Ean13 = '" + options.isbn + "'";
|
|
}
|
|
}
|
|
}
|
|
|
|
let recproducts = await getTableContent(options);
|
|
|
|
let idRecUpdated = null;
|
|
|
|
if (!tools.isArray(recproducts)) {
|
|
console.error('Error: ', recproducts);
|
|
mylog += recproducts + '\n';
|
|
} else {
|
|
numrec = recproducts?.length || 0;
|
|
|
|
console.log('numrec', numrec);
|
|
}
|
|
|
|
let rimuoviTabellePerIniziare = false;
|
|
|
|
let count = 0;
|
|
if (Array.isArray(recproducts)) {
|
|
if (recproducts.length > 10 && lavoromassivo && options.rimuovieventualiCancellati) {
|
|
// rimuovi dalla tabella productInfo tutti i campi date_updated_fromGM
|
|
const result = await ProductInfo.updateMany(
|
|
{ idapp: options.idapp },
|
|
{ $unset: { date_updated_fromGM: null } }
|
|
);
|
|
let quanti_rimossi = result.modifiedCount;
|
|
console.log(`Sbianca date_updated_fromGM da ProductInfo: (${quanti_rimossi} su ${result.matchedCount})`);
|
|
rimuoviTabellePerIniziare = true;
|
|
}
|
|
|
|
if (false) {
|
|
const gruppiPerIsbn = recproducts.reduce((map, product) => {
|
|
const isbn = product.Ean13;
|
|
if (!map.has(isbn)) {
|
|
map.set(isbn, [product]);
|
|
} else {
|
|
map.get(isbn).push(product);
|
|
}
|
|
return map;
|
|
}, new Map());
|
|
|
|
const isbnConMultipliRecord = Array.from(gruppiPerIsbn.entries())
|
|
.filter(([isbn, products]) => products.length > 1)
|
|
.map(([isbn]) => isbn);
|
|
|
|
recproducts = recproducts.filter((product) => isbnConMultipliRecord.includes(product.Ean13));
|
|
|
|
console.log(
|
|
`Trovati ${isbnConMultipliRecord.length} record con ISBN duplicati: ${isbnConMultipliRecord.join(', ')}`
|
|
);
|
|
}
|
|
|
|
for (const recproduct of recproducts) {
|
|
await this.elaboraProdotto(recproduct, opt);
|
|
|
|
const sku = recproduct.IdArticolo;
|
|
|
|
if (sku) {
|
|
await T_WEB_ArticoliFatturati.updateStatisticsFatt(sku.toString(), options.idapp, true);
|
|
await T_WEB_Ordini.updateStatisticsOrders(sku.toString(), options.idapp, true);
|
|
}
|
|
count++;
|
|
|
|
if (count % 50 === 0) {
|
|
const percentuale = Math.round((count / numrec) * 100);
|
|
console.log(
|
|
` *** RECORD ${count} - IMPORTATI: ${opt.imported} AGGIORNATI = ${opt.updated} (su ${numrec} RECORD) - Completato al ${percentuale}%`
|
|
);
|
|
}
|
|
//}
|
|
}
|
|
|
|
if (rimuoviTabellePerIniziare && options.rimuovieventualiCancellati) {
|
|
await ProductInfo.removeProductInfoWithoutDateUpdatedFromGM(options.idapp);
|
|
}
|
|
if (myjob) await myjob.terminateJob();
|
|
}
|
|
|
|
if (numrec > 1) {
|
|
opt.idRecUpdated = null;
|
|
}
|
|
|
|
if (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,
|
|
idRecUpdated: opt.idRecUpdated,
|
|
table: opt.table,
|
|
};
|
|
} catch (e) {
|
|
mylog +=
|
|
'ERRORE ! *** IMPORTATI: ' + opt?.imported + ' AGGIORNATI = ' + opt?.updated + ' (su ' + numrec + ' RECORD)';
|
|
opt.logerror = e.message;
|
|
if (myjob) await myjob.terminateJob(true);
|
|
console.error(e.message);
|
|
return { updated: opt.updated, imported: opt.imported, errors: opt.errors, mylog, logerror: opt.logerror };
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Funzione principale per importare il catalogo.
|
|
*/
|
|
async importaCatalogo(data) {
|
|
let updated = 0,
|
|
imported = 0,
|
|
errors = 0,
|
|
indice = 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 });
|
|
indice++;
|
|
}
|
|
|
|
const percentuale = ((indice / dataObjects.length) * 100).toFixed(2);
|
|
console.log(
|
|
`*** RECORD: ${indice} - IMPORTATI: ${imported}, AGGIORNATI = ${updated} (su ${dataObjects.length} RECORD) - Completamento: ${percentuale}%`
|
|
);
|
|
return { updated, imported, errors };
|
|
} catch (e) {
|
|
console.error(e.message);
|
|
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, deleted: false };
|
|
|
|
if (options.inputdaGM) product = await 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);
|
|
await this.gestisciCollana(productInfo, product);
|
|
|
|
const risrecInfo = await ProductInfo.findOneAndUpdate(
|
|
{ code: productInfo.code },
|
|
{ $set: productInfo },
|
|
{ new: true, upsert: true, returnOriginal: false }
|
|
).lean();
|
|
|
|
if (risrecInfo) {
|
|
product.idProductInfo = risrecInfo._id;
|
|
this.queryprod = { idProductInfo: product.idProductInfo };
|
|
|
|
const aggiornatoimg = await this.aggiornaImmagineSeNecessario(risrecInfo);
|
|
if (!aggiornatoimg?.delete) {
|
|
await this.gestisciGasOrdine(product, risrecInfo);
|
|
await this.gestisciVariazioni(product, risrecInfo, options);
|
|
}
|
|
} else {
|
|
console.error('Errore ProductInfo:', product.code);
|
|
options.errors++;
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
|
|
if (recGas) {
|
|
this.queryprod = { ...this.queryprod, idGasordine: recGas._id };
|
|
}
|
|
|
|
this.recProductExist = await Product.findOne(this.queryprod).lean();
|
|
|
|
if (!this.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,
|
|
idCollana: product.idCollana,
|
|
numCollana: product.numCollana,
|
|
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,
|
|
...(product.date_updated_fromGM ? { date_updated_fromGM: product.date_updated_fromGM } : {}),
|
|
};
|
|
} 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';
|
|
}
|
|
}
|
|
|
|
async 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 magazzino_macro = 'Gruppo Macro';
|
|
|
|
let recstorehouse = await Storehouse.findOne({ idapp, name: magazzino_macro }).lean();
|
|
if (!recstorehouse) {
|
|
// Non esiste questo produttore, quindi lo creo !
|
|
recstorehouse = new Storehouse({ idapp, name: magazzino_macro });
|
|
ris = await recstorehouse.save();
|
|
recstorehouse = await Storehouse.findOne({ idapp, name: prod.magazzino_name }).lean();
|
|
}
|
|
|
|
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: '',
|
|
collezione: productGM.DescrizioneCollana,
|
|
numCollana: productGM.IdCollana,
|
|
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,
|
|
idTipologia: productGM.IdTipologia,
|
|
idTipoFormato: productGM.IdTipoFormato,
|
|
Pagine: productGM.Pagine,
|
|
misure: productGM.Misure,
|
|
Edizione: productGM.Edizione,
|
|
ristampa: productGM.Ristampa,
|
|
eta: productGM.FasciaEta,
|
|
// addtocart_link: '',
|
|
stockQty: productGM.QtaDisponibile || undefined,
|
|
date_pub: productGM.DataPubblicazione ? tools.getDateFromISOString(productGM.DataPubblicazione) : null,
|
|
sottotitolo: productGM.Sottotitolo,
|
|
productTypes: [shared_consts.PRODUCTTYPE.PRODUCT],
|
|
date_updated_fromGM: new Date(),
|
|
idStorehouses: [recstorehouse._id],
|
|
};
|
|
|
|
let vers = 0;
|
|
|
|
if (productGM.DescrizioneTipologia === 'Usato') vers = shared_consts.PRODUCTTYPE.USATO;
|
|
if (productGM.DescrizioneTipologia === 'Download') vers = shared_consts.PRODUCTTYPE.DOWNLOAD;
|
|
else if (productGM.DescrizioneTipologia === 'DVD') vers = shared_consts.PRODUCTTYPE.DVD;
|
|
else if (productGM.DescrizioneTipologia === 'Epub') vers = shared_consts.PRODUCTTYPE.EPUB;
|
|
else if (productGM.DescrizioneTipologia === 'Mobi') vers = shared_consts.PRODUCTTYPE.MOBI;
|
|
else if (productGM.DescrizioneTipologia === 'PDF') vers = shared_consts.PRODUCTTYPE.PDF;
|
|
else if (productGM.DescrizioneTipologia === 'Streaming') vers = shared_consts.PRODUCTTYPE.STREAMING;
|
|
else vers = shared_consts.PRODUCTTYPE.NUOVO;
|
|
|
|
recproduct.Versione = vers;
|
|
|
|
return recproduct;
|
|
}
|
|
|
|
/**
|
|
* Gestisce le categorie e sottocategorie del prodotto.
|
|
*/
|
|
async gestisciCategorie(productInfo, product) {
|
|
try {
|
|
if (product.DescrArgomento) {
|
|
productInfo.idCatProds = [];
|
|
const reccateg = await CatProd.findOne({ idapp: this.idapp, name: product.DescrArgomento });
|
|
let nuovaCategoria = null;
|
|
if (!reccateg) {
|
|
nuovaCategoria = new CatProd({ idapp: this.idapp, name: product.DescrArgomento });
|
|
await nuovaCategoria.save();
|
|
}
|
|
|
|
|
|
if (!reccateg?.idArgomento && product.DescrArgomento) {
|
|
// Se non c'è l'argomento, allora lo cerco nel DB
|
|
const recarg = await T_Web_Argomenti.findOne({ Descrizione: product.DescrArgomento }).lean();
|
|
if (recarg) {
|
|
reccateg.idArgomento = recarg.IdArgomento;
|
|
await reccateg.save();
|
|
}
|
|
}
|
|
|
|
|
|
const myriscat = reccateg?._id || (nuovaCategoria ? nuovaCategoria._id : null);
|
|
if (myriscat) productInfo.idCatProds.push(myriscat);
|
|
} else {
|
|
if (product.categories) {
|
|
// const arrcat = product.categories.trim().split(',');
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error('Errore gestisciCategorie:', error);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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();
|
|
|
|
let nuovoEditore = null;
|
|
if (!recpublisher) {
|
|
nuovoEditore = new Publisher({ idapp: this.idapp, name: publisher });
|
|
await nuovoEditore.save();
|
|
if (!nuovoEditore._id) {
|
|
console.error('Errore gestisciEditore: nuovoEditore non ha id');
|
|
return;
|
|
}
|
|
}
|
|
if (recpublisher?._id || nuovoEditore?._id) productInfo.idPublisher = recpublisher?._id || nuovoEditore._id;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gestisce la collana del prodotto.
|
|
*/
|
|
async gestisciCollana(productInfo, product) {
|
|
if (product.collezione && product.numCollana) {
|
|
const collana = product.collezione.trim();
|
|
const reccollana = await Collana.findOne({ idapp: this.idapp, title: collana }).lean();
|
|
|
|
let nuovaCollana = null;
|
|
if (!reccollana) {
|
|
nuovaCollana = new Collana({ idapp: this.idapp, idCollana: product.numCollana, title: collana });
|
|
await nuovaCollana.save();
|
|
if (!nuovaCollana._id) {
|
|
console.error('Errore gestisciCollana: nuovaCollana non ha id');
|
|
return;
|
|
}
|
|
}
|
|
if (reccollana?._id || nuovaCollana?._id) productInfo.idCollana = reccollana?._id || nuovaCollana._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 });
|
|
}
|
|
|
|
return aggiornatoimg;
|
|
}
|
|
|
|
/**
|
|
* 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 || '',
|
|
idTipologia: product.idTipologia || '',
|
|
idTipoFormato: product.idTipoFormato || '',
|
|
// tipologia: product.Tipologia || '',
|
|
edizione: product.Edizione || '',
|
|
pagine: tools.isValidNumber(product.Pagine) ? tools.convstrToInt(product.Pagine) : 0,
|
|
misure: product.misure || '',
|
|
ristampa: product.ristampa || '',
|
|
eta: product.eta || '',
|
|
addtocart_link: product.addtocart_link || '',
|
|
quantita: product.stockQty ? parseInt(product.stockQty) : 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 recold = await Product.findOne(this.queryprod).lean();
|
|
const variazione = this.preparaVariazione(product);
|
|
|
|
const myproduct = {
|
|
...product,
|
|
...(!product.isbn ? [{ isbn: risrecInfo.code }] : []),
|
|
...(!product.maxbookableGASQty && risrecInfo.maxbookableGASQty
|
|
? [{ maxbookableGASQty: risrecInfo.maxbookableGASQty }]
|
|
: []),
|
|
idapp: this.idapp,
|
|
arrvariazioni: [variazione],
|
|
};
|
|
|
|
let risultupdate = null;
|
|
|
|
if (recold) {
|
|
const arrvariazioni = this.aggiornaVariazioni(recold.arrvariazioni, variazione);
|
|
const updatedDoc = await Product.findOneAndUpdate(
|
|
this.queryprod,
|
|
{ $set: { arrvariazioni } },
|
|
{
|
|
upsert: true,
|
|
new: true, // restituisce il documento aggiornato
|
|
includeResultMetadata: true,
|
|
}
|
|
);
|
|
if (updatedDoc && updatedDoc.lastErrorObject) {
|
|
const wasUpserted = updatedDoc.lastErrorObject.upserted !== undefined;
|
|
const wasUpdated = updatedDoc.lastErrorObject.n === 1 && !wasUpserted;
|
|
|
|
if (wasUpserted || wasUpdated) {
|
|
options.updated++;
|
|
options.table = 'products';
|
|
options.idRecUpdated = wasUpserted ? updatedDoc.lastErrorObject.upserted : updatedDoc.value._id;
|
|
}
|
|
}
|
|
|
|
if (recold.isbn !== risrecInfo.code) {
|
|
product.isbn = risrecInfo.code;
|
|
}
|
|
}
|
|
if (!recold || this.isModified(recold, myproduct) || !this.recProductExist) {
|
|
const updatedDoc = await Product.findOneAndUpdate(
|
|
this.queryprod,
|
|
{ $set: myproduct },
|
|
{
|
|
new: true,
|
|
upsert: true,
|
|
includeResultMetadata: true,
|
|
}
|
|
);
|
|
if (updatedDoc && updatedDoc.lastErrorObject) {
|
|
const wasUpserted = updatedDoc.lastErrorObject.upserted !== undefined;
|
|
const wasUpdated = updatedDoc.lastErrorObject.n === 1 && !wasUpserted;
|
|
|
|
if (wasUpserted || wasUpdated) {
|
|
options.imported++;
|
|
options.table = 'products';
|
|
options.idRecUpdated = wasUpserted ? updatedDoc.lastErrorObject.upserted : updatedDoc.value._id;
|
|
}
|
|
}
|
|
}
|
|
|
|
// console.log('risultupdate', risultupdate);
|
|
}
|
|
|
|
/**
|
|
* Verifica se i campi nella lista sono stati modificati da una versione all'altra.
|
|
* @param {Object} recordOld - record vecchio
|
|
* @param {Object} recordNew - record nuovo
|
|
* @param {string[]} listaCampi - lista dei campi da verificare
|
|
* @returns {boolean} true se i campi sono stati modificati
|
|
*/
|
|
isModified(recordOld, recordNew) {
|
|
const listaCampi = [
|
|
'idapp',
|
|
'isbn',
|
|
'price',
|
|
'stockQty',
|
|
//++FIELD_PRODUCT
|
|
];
|
|
return listaCampi.some((campo) => recordOld[campo] !== recordNew[campo]);
|
|
}
|
|
|
|
async getStat() {
|
|
let mystr = '';
|
|
|
|
const ris = await ProductInfo.countDocuments({
|
|
$or: [{ date_updated_fromGM: { $exists: false } }, { date_updated_fromGM: null }],
|
|
});
|
|
mystr += `${ris} ProductInfo non aggiornati da GM, quindi da cancellare ! \n`;
|
|
|
|
return mystr;
|
|
}
|
|
}
|
|
|
|
module.exports = Macro;
|