2453 lines
81 KiB
JavaScript
Executable File
2453 lines
81 KiB
JavaScript
Executable File
const express = require('express');
|
||
const router = express.Router();
|
||
const mongoose = require('mongoose').set('debug', false);
|
||
const { CfgServer } = require('../models/cfgserver');
|
||
|
||
const shared_consts = require('../tools/shared_nodejs');
|
||
|
||
const tools = require('../tools/general');
|
||
|
||
const Macro = require('../modules/Macro'); // Importa la classe Macro
|
||
|
||
const fs = require('fs'); // 👈 Usa il modulo promises
|
||
|
||
const { City } = require('../models/city');
|
||
const Product = require('../models/product');
|
||
const Inventariogm = require('../models/inventariogm');
|
||
const Importamacro = require('../models/importamacro');
|
||
const ImportaDescr = require('../models/importadescr');
|
||
const ImportaIsbn = require('../models/importaisbn');
|
||
const CatProd = require('../models/catprod');
|
||
const Collana = require('../models/collana');
|
||
const Author = require('../models/author');
|
||
const Publisher = require('../models/publisher');
|
||
const SubCatProd = require('../models/subcatprod');
|
||
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 path = require('path');
|
||
|
||
const gs = require('ghostscript4js');
|
||
|
||
const { PDFDocument, rgb } = require('pdf-lib');
|
||
|
||
const pdf = require('pdf-parse');
|
||
|
||
var { authenticate } = require('../middleware/authenticate');
|
||
|
||
const multer = require('multer');
|
||
|
||
const DIR_PDF_IN = __dirname + '/upload/files_input/';
|
||
// const DIR_PDF_OUT = __dirname + '/upload/files_output/';
|
||
|
||
const upload = multer({ dest: DIR_PDF_IN });
|
||
|
||
const util = require('util');
|
||
const cwd = process.cwd();
|
||
|
||
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;
|
||
|
||
let idArgomentoNum = null;
|
||
|
||
let productInfo = null;
|
||
|
||
if (product.ListaArgomenti) {
|
||
idArgomentoNum = parseInt(product.ListaArgomenti);
|
||
productInfo = { ...recproductInfoAttuale, idArgomento: idArgomentoNum };
|
||
} else {
|
||
productInfo = { ...recproductInfoAttuale };
|
||
}
|
||
|
||
let reccatprod = await findOrCreateCatProd(idapp, idArgomentoNum, mycatstr);
|
||
|
||
if (reccatprod) {
|
||
updateProductInfoCatProds(productInfo, reccatprod);
|
||
}
|
||
|
||
return productInfo;
|
||
}*/
|
||
|
||
async function findOrCreateCatProd(idapp, idArgomento, DescrArgomento) {
|
||
let reccatprod = null;
|
||
if (idArgomento) {
|
||
reccatprod = await CatProd.findOne({ idapp, idArgomento }).lean();
|
||
}
|
||
|
||
if (!reccatprod) {
|
||
reccatprod = await CatProd.findOne({ idapp, name: DescrArgomento }).lean();
|
||
if (reccatprod) {
|
||
if (idArgomento) {
|
||
await CatProd.findOneAndUpdate(
|
||
{ _id: reccatprod._id },
|
||
{ $set: { idArgomento } },
|
||
{
|
||
returnDocument: 'after',
|
||
upsert: false,
|
||
}
|
||
);
|
||
}
|
||
} else {
|
||
if (idArgomento) {
|
||
try {
|
||
reccatprod = new CatProd({ idapp, idArgomento, name: DescrArgomento });
|
||
await reccatprod.save();
|
||
} catch (e) {
|
||
console.error('Errore nella creazione di CatProd:', e);
|
||
return null;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
return reccatprod;
|
||
}
|
||
|
||
function updateProductInfoCatProds(productInfo, reccatprod) {
|
||
if (productInfo) {
|
||
// 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.length > 0 &&
|
||
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, ' Libro:', productInfo.name);
|
||
}
|
||
}
|
||
}
|
||
/*
|
||
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:
|
||
|
||
Opzioni di -dPDFSETTINGS
|
||
/screen: Buona per la visualizzazione su schermo; bassa qualità e dimensione del file ridotta.
|
||
/ebook: Ottimizza il PDF per la lettura su ebook; qualità media e dimensione media.
|
||
/printer: Ottimizza il PDF per la stampa di qualità; migliora la risoluzione rispetto a /ebook.
|
||
/prepress: Ottimizza per la stampa di alta qualità; ideale per progetti di stampa professionali.
|
||
/default: Usa impostazioni predefinite; generalmente fornisce un buon equilibrio tra qualità e dimensione.
|
||
*/
|
||
|
||
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);
|
||
}
|
||
}
|
||
|
||
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);
|
||
}
|
||
|
||
// 3. Test comando di sistema
|
||
const { exec } = require('child_process');
|
||
const util = require('util');
|
||
const execAsync = util.promisify(exec);
|
||
|
||
try {
|
||
console.log('Testing gs command from system...');
|
||
const { stdout, stderr } = await execAsync('gs -version');
|
||
console.log('GS Version stdout:', stdout);
|
||
console.log('GS Version stderr:', stderr);
|
||
} catch (error) {
|
||
console.log('System gs command failed:', error.message);
|
||
}
|
||
|
||
// 4. Test scrittura file
|
||
const fs = require('fs').promises;
|
||
const path = require('path');
|
||
const testFile = path.join(process.cwd(), 'test_write.txt');
|
||
|
||
try {
|
||
await fs.writeFile(testFile, 'test content');
|
||
console.log('File write test: SUCCESS');
|
||
await fs.unlink(testFile);
|
||
} catch (error) {
|
||
console.log('File write test: FAILED -', error.message);
|
||
}
|
||
}
|
||
|
||
// ALTERNATIVA 1: Usando child_process direttamente
|
||
async function convertPDF_ChildProcess(inputFile, outputFile, width, height, compressionLevel = 'screen') {
|
||
const { spawn } = require('child_process');
|
||
const path = require('path');
|
||
|
||
console.log('=== CONVERSIONE CON CHILD_PROCESS E COMPRESSIONE ===');
|
||
|
||
// Verifica input
|
||
if (!(await tools.isFileExistsAsync(inputFile))) {
|
||
throw new Error(`File input non trovato: ${inputFile}`);
|
||
}
|
||
|
||
// Assicurati che la directory output esista
|
||
const outputDir = path.dirname(outputFile);
|
||
const fs = require('fs').promises;
|
||
try {
|
||
await fs.mkdir(outputDir, { recursive: true });
|
||
} catch (error) {
|
||
// Directory già esistente, ok
|
||
}
|
||
|
||
// const widthPt = Math.round(width * 28.34646);
|
||
// const heightPt = Math.round(height * 28.34646);
|
||
const widthPt = Math.round(width * 28.34646 * 10);
|
||
const heightPt = Math.round(height * 28.34646 * 10);
|
||
|
||
// Parametri di compressione ottimizzati
|
||
const compressionSettings = {
|
||
maximum: [
|
||
'-dPDFSETTINGS=/screen',
|
||
'-dDownsampleColorImages=true',
|
||
'-dColorImageResolution=72',
|
||
'-dDownsampleGrayImages=true',
|
||
'-dGrayImageResolution=72',
|
||
'-dDownsampleMonoImages=true',
|
||
'-dMonoImageResolution=72',
|
||
],
|
||
high: [
|
||
'-dPDFSETTINGS=/ebook',
|
||
'-dDownsampleColorImages=true',
|
||
'-dColorImageResolution=150',
|
||
'-dDownsampleGrayImages=true',
|
||
'-dGrayImageResolution=150',
|
||
],
|
||
printer: ['-dPDFSETTINGS=/printer', '-dDownsampleColorImages=true', '-dColorImageResolution=300'],
|
||
screen: [
|
||
'-dPDFSETTINGS=/screen',
|
||
'-dDownsampleColorImages=true',
|
||
'-dColorImageResolution=96',
|
||
'-dDownsampleGrayImages=true',
|
||
'-dGrayImageResolution=96',
|
||
],
|
||
};
|
||
|
||
return new Promise((resolve, reject) => {
|
||
const args = [
|
||
'-sDEVICE=pdfwrite',
|
||
'-dCompatibilityLevel=1.4',
|
||
'-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) {
|
||
// Estrai le dimensioni delle pagine utilizzando pdf-lib
|
||
const existingPdfBytes = fs.readFileSync(inputFile);
|
||
const pdfDoc = await PDFDocument.load(existingPdfBytes);
|
||
|
||
// Ottieni informazioni sulle dimensioni delle pagine
|
||
const pages = pdfDoc.getPages();
|
||
const pageInfo = pages.map((page) => {
|
||
const { width, height } = page.getSize();
|
||
return {
|
||
width: width, // in punti
|
||
height: height, // in punti
|
||
};
|
||
});
|
||
|
||
// Estrai informazioni testuali e numero di pagine utilizzando pdf-parse
|
||
const dataBuffer = fs.readFileSync(inputFile);
|
||
const data = await pdf(dataBuffer);
|
||
|
||
const dpiInfo = {
|
||
numPages: data.numpages,
|
||
pageInfo: pageInfo,
|
||
};
|
||
|
||
console.log('DPI info might require image extraction (not available directly):');
|
||
console.log('Number of Pages:', dpiInfo.numPages);
|
||
console.log('Page Dimensions (in points):', dpiInfo.pageInfo);
|
||
}
|
||
|
||
async function convertPDF_PdfLib(idapp, inputFile, outputFile, options) {
|
||
if (!(await tools.isFileExistsAsync(inputFile))) {
|
||
throw new Error(`Il file di input non esiste: ${inputFile}`);
|
||
}
|
||
|
||
console.log('START convertPDF_PdfLib...');
|
||
|
||
try {
|
||
options.filenameIn = inputFile;
|
||
options.filenameOut = outputFile;
|
||
const uscita = await ConvertPDF_Generatore(options, options.stampa);
|
||
|
||
return uscita;
|
||
} catch (e) {
|
||
console.error('Errore: ', e.message);
|
||
return '';
|
||
}
|
||
}
|
||
|
||
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 passato in Ingresso.' };
|
||
}
|
||
|
||
let marginTop = instampa ? parseFloat(options.print_top) : 0;
|
||
let marginRight = instampa ? parseFloat(options.print_right) : 0;
|
||
let marginBottom = instampa ? parseFloat(options.print_bottom) : 0;
|
||
let marginLeft = instampa ? parseFloat(options.print_left) : 0;
|
||
|
||
if (instampa) {
|
||
suffisso_filename = '_stampabile_generato';
|
||
} else {
|
||
suffisso_filename = '_generato';
|
||
}
|
||
|
||
let outputFilename = suffisso_filename
|
||
? tools.aggiungiSuffissoAlNomeFile(options.filenameOut, suffisso_filename)
|
||
: options.filenameOut;
|
||
|
||
// controlla se outputFilename non ha directory allora gliela aggiungo
|
||
if (!path.dirname(outputFilename)) {
|
||
outputFilename = path.join(options.dir_out, outputFilename);
|
||
}
|
||
|
||
const outputFullPathFileName = outputFilename;
|
||
|
||
await leggiDimensioniPdf(options.filenameIn);
|
||
|
||
try {
|
||
// Leggi il PDF originale
|
||
const existingPdfBytes = await fs.promises.readFile(options.filenameIn);
|
||
const srcPdfDoc = await PDFDocument.load(existingPdfBytes); // Documento sorgente
|
||
const destPdfDoc = await PDFDocument.create(); // Nuovo documento vuoto
|
||
|
||
const pages = srcPdfDoc.getPages();
|
||
|
||
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;
|
||
|
||
// Embed della pagina originale nel nuovo documento
|
||
const embeddedPages = await destPdfDoc.embedPdf(srcPdfDoc, [i]); // Embeddiamo la pagina i-esima
|
||
const embeddedPage = embeddedPages[0]; // Otteniamo l'oggetto embedded
|
||
|
||
// Aggiungi una nuova pagina alla stessa dimensione dell’originale
|
||
const newPage = destPdfDoc.addPage([width, height]);
|
||
|
||
// Disegna la pagina embedded nella nuova pagina
|
||
newPage.drawPage(embeddedPage, {
|
||
x: marginLeft,
|
||
y: marginBottom,
|
||
width: newWidth,
|
||
height: newHeight,
|
||
});
|
||
}
|
||
|
||
// Salva il nuovo PDF
|
||
const pdfBytes = await destPdfDoc.save();
|
||
|
||
const dirUscita = path.dirname(outputFullPathFileName);
|
||
if (!(await tools.isDirectoryAsync(dirUscita))) {
|
||
await fs.promises.mkdir(dirUscita, { recursive: true });
|
||
}
|
||
|
||
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: (instampa = ${instampa}): ` + error.message;
|
||
console.error(log);
|
||
return {
|
||
err: log,
|
||
fileout: tools.removePathDirByFileName(options.idapp, fileout),
|
||
fileout_compressed: tools.removePathDirByFileName(options.idapp, fileout_compressed),
|
||
};
|
||
}
|
||
|
||
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) {
|
||
return res.status(400).send('No file uploaded.');
|
||
}
|
||
|
||
const inputFile = req.file.path;
|
||
const {
|
||
width,
|
||
height,
|
||
compressione,
|
||
dir_out,
|
||
file_out,
|
||
idapp,
|
||
print_top = '0',
|
||
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: tools.getdirByIdApp(idapp) + '/' + dir_out,
|
||
file_out,
|
||
idapp,
|
||
print_top,
|
||
print_right,
|
||
print_bottom,
|
||
print_left,
|
||
stampa: stampa === '1',
|
||
};
|
||
|
||
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;
|
||
}
|
||
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
|
||
const risout = await convertPDF_PdfLib(idapp, inputFile, outputFile, options);
|
||
|
||
if (salvasufiledascaricare === 'true') {
|
||
// Invia il file come download
|
||
return res.download(outputFile, options.file_out, async (err) => {
|
||
await cleanupFiles(inputFile, outputFile);
|
||
if (err) {
|
||
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 {
|
||
// Non inviare file, solo risposta JSON
|
||
await cleanupFiles(inputFile, ''); // pulisci solo inputFile
|
||
return res.status(200).send(risout);
|
||
}
|
||
} catch (error) {
|
||
console.error('Errore durante la conversione:', error);
|
||
await cleanupFiles(inputFile, '');
|
||
if (!res.headersSent) {
|
||
return res.status(500).send(`Errore durante la conversione del PDF: ${error.message}`);
|
||
}
|
||
}
|
||
});
|
||
|
||
async function cleanupFiles(inputFile, outputFile) {
|
||
if (inputFile) {
|
||
await tools.deleteFile(inputFile).catch((err) => {
|
||
console.error('Errore durante la rimozione del file di INPUT:', err);
|
||
});
|
||
}
|
||
if (outputFile) {
|
||
await tools.deleteFile(outputFile).catch((err) => {
|
||
console.error('Errore durante la rimozione del file di output:', err);
|
||
});
|
||
}
|
||
}
|
||
|
||
router.post('/updateval', authenticate, async (req, res) => {
|
||
console.log('/updateval', req.body.pairval);
|
||
idapp = req.body.idapp;
|
||
pair = req.body.pairval;
|
||
|
||
return await CfgServer.findOneAndUpdate(
|
||
{ chiave: pair.chiave, idapp, userId: pair.userId },
|
||
{ $set: pair },
|
||
{ new: false }
|
||
)
|
||
.then((item) => {
|
||
if (!!item) {
|
||
res.status(200).send();
|
||
} else {
|
||
res.status(400).send();
|
||
}
|
||
})
|
||
.catch((err) => {
|
||
console.log('ERR:', err);
|
||
res.status(400).send();
|
||
});
|
||
});
|
||
|
||
function fixURL(url) {
|
||
return url.replace(/https:\//g, 'https://');
|
||
}
|
||
|
||
async function completaSettaggioProduct_AndProductInfo(
|
||
arrcampi_productInfo,
|
||
arrcampi_product,
|
||
rec,
|
||
product,
|
||
productInfo
|
||
) {
|
||
try {
|
||
if (shared_consts.CAMPI_PRODUCTINFO_CONVERT.includes('weight_and_unit')) {
|
||
if (rec.hasOwnProperty('weight_and_unit')) {
|
||
const ris1 = tools.getWeightAndUnitByText(rec['weight_and_unit']);
|
||
if (ris1) {
|
||
productInfo.weight = ris1.weight;
|
||
productInfo.unit = ris1.unit;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (shared_consts.CAMPI_PRODUCTINFO_CONVERT.includes('weight_and_unit_lordo')) {
|
||
if (rec.hasOwnProperty('weight_and_unit_lordo')) {
|
||
const ris2 = tools.getWeightAndUnitByText(rec['weight_and_unit_lordo']);
|
||
if (ris2) {
|
||
productInfo.weight_lordo = ris2.weight;
|
||
productInfo.unit_lordo = ris2.unit;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (rec.hasOwnProperty('link_scheda')) {
|
||
if (fixURL(rec['link_scheda'])) productInfo['link_scheda'] = fixURL(rec['link_scheda']);
|
||
}
|
||
|
||
for (const campo of shared_consts.PRODUCTINFO.CAMPI_FIRST_UPPERCASE) {
|
||
if (rec.hasOwnProperty(campo)) {
|
||
let mystr = tools.capitalize(rec[campo]).trim();
|
||
if (mystr) productInfo[campo] = mystr;
|
||
}
|
||
}
|
||
|
||
// Conversione in Euro
|
||
for (campoprezzo of shared_consts.CAMPI_EURO) {
|
||
if (rec.hasOwnProperty(campoprezzo)) {
|
||
product[campoprezzo] = tools.convertPriceEurToValue(rec[campoprezzo]);
|
||
}
|
||
}
|
||
|
||
if (!rec.hasOwnProperty('img') && product.code) {
|
||
productInfo.imagefile = product.code + '.jpg';
|
||
} else {
|
||
if (rec.hasOwnProperty('img')) {
|
||
if (rec['img']) {
|
||
productInfo.imagefile = rec['img'];
|
||
} else {
|
||
productInfo.imagefile = '';
|
||
}
|
||
}
|
||
}
|
||
|
||
if (rec.hasOwnProperty('productTypes')) {
|
||
productInfo.productTypes = productInfo.productTypes;
|
||
} else {
|
||
productInfo.productTypes = [shared_consts.PRODUCTTYPE.PRODUCT];
|
||
}
|
||
|
||
return { product, productInfo };
|
||
} catch (e) {
|
||
console.error('Err', e);
|
||
}
|
||
|
||
return { product, productInfo };
|
||
}
|
||
|
||
function getValoriAndIndice(dati, arrinclude) {
|
||
const campi = dati;
|
||
|
||
for (const key in campi) {
|
||
if (Object.hasOwnProperty.call(obj, key)) {
|
||
const value = obj[key];
|
||
console.log(`${key}: ${value}`);
|
||
}
|
||
}
|
||
|
||
const risultato = campi.map((campo, indice) => {
|
||
let mycampo = campo.trim();
|
||
if (arrinclude) {
|
||
if (arrinclude.includes(mycampo)) return { name: mycampo, ind: indice };
|
||
} else {
|
||
return { name: mycampo, ind: indice };
|
||
}
|
||
});
|
||
|
||
return risultato;
|
||
}
|
||
|
||
function getValoriAndIndice_ProductInfo(dati) {
|
||
//return getValoriAndIndice(dati, shared_consts.CAMPI_PRODUCTINFO)
|
||
return shared_consts.CAMPI_PRODUCTINFO;
|
||
}
|
||
|
||
function getValoriAndIndice_Product(dati) {
|
||
//return getValoriAndIndice(dati, shared_consts.CAMPI_PRODUCT);
|
||
return shared_consts.CAMPI_PRODUCT;
|
||
}
|
||
|
||
async function extractArrayDataFromCSV(idapp, rec) {
|
||
try {
|
||
// la prima riga contiene il nome della proprietà:
|
||
let productInfo = {
|
||
idapp: idapp,
|
||
idCatProds: [],
|
||
idSubCatProds: [],
|
||
};
|
||
|
||
let product = {
|
||
idapp,
|
||
};
|
||
|
||
arrcampi_productInfo = getValoriAndIndice_ProductInfo(null);
|
||
arrcampi_product = getValoriAndIndice_Product(null);
|
||
|
||
for (const campoobj of arrcampi_productInfo) {
|
||
// TODO: controlla che il campo rec[campoobj.name] esista anche se minuscolo/maiuscolo
|
||
const mykey = Object.keys(rec).find((key) => key.toLowerCase() === campoobj.name.toLowerCase());
|
||
if (mykey) {
|
||
let myval = tools.ripulisciCampo(rec[mykey]);
|
||
productInfo[campoobj.name] =
|
||
myval === 'TRUE' || myval.toUpperCase() === 'SI'
|
||
? true
|
||
: myval === 'FALSE' || myval.toUpperCase() === 'NO'
|
||
? false
|
||
: myval;
|
||
}
|
||
}
|
||
|
||
for (const campoobj of arrcampi_product) {
|
||
if (rec.hasOwnProperty(campoobj)) product[campoobj] = rec[campoobj];
|
||
}
|
||
|
||
const ris = await completaSettaggioProduct_AndProductInfo(
|
||
arrcampi_productInfo,
|
||
arrcampi_product,
|
||
rec,
|
||
product,
|
||
productInfo
|
||
);
|
||
|
||
/*
|
||
// code: product.code,
|
||
name: product.name,
|
||
link: product.link,
|
||
idCatProds: [],
|
||
idSubCatProds: [],
|
||
img: 'upload/products/' + product.code + '.jpg',
|
||
weight: product.weight,
|
||
unit: tools.getIdUnitsByText(product.unit),
|
||
}
|
||
|
||
|
||
*/
|
||
|
||
return ris;
|
||
} catch (e) {
|
||
console.error('Err', e);
|
||
}
|
||
|
||
return dataObjects;
|
||
}
|
||
|
||
function extractNameAndSurnameByComplete(name_complete) {
|
||
if (name_complete) {
|
||
const name = name_complete.split(' ')[0];
|
||
const surname = name_complete.split(' ')[1];
|
||
return { name, surname };
|
||
} else {
|
||
return { name: '', surname: '' };
|
||
}
|
||
}
|
||
|
||
function getvalueByJsonText(valore) {
|
||
if (valore && valore['#text']) {
|
||
if (valore['#text']) return valore['#text'];
|
||
else return value;
|
||
}
|
||
|
||
return null;
|
||
}
|
||
|
||
router.post('/import', authenticate, async (req, res) => {
|
||
try {
|
||
const cmd = req.body.cmd;
|
||
const idapp = req.body.idapp;
|
||
const data = req.body.data;
|
||
const options = req.body.data.options;
|
||
|
||
const liste = require('../data/liste');
|
||
let dataObjects = null;
|
||
|
||
if (cmd === shared_consts.Cmd.CITIES_SERVER) {
|
||
return await City.insertMany(liste.Comuni).then((ris) => {
|
||
return res.status(200).send(true);
|
||
});
|
||
} else if (cmd === shared_consts.Cmd.INVENTARIO) {
|
||
dataObjects = JSON.parse(`[${data.arrdata}]`);
|
||
let updated = 0;
|
||
let imported = 0;
|
||
let errors = 0;
|
||
|
||
for (const recinv of dataObjects) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let inventario = recinv;
|
||
|
||
inventario.idapp = idapp;
|
||
|
||
let risrec = await Inventariogm.findOneAndUpdate(queryprod, { $set: inventario }, { new: true, upsert: true });
|
||
}
|
||
} else if (cmd === shared_consts.Cmd.MACRO_DESCRELINKSITOWEB) {
|
||
let updated = 0;
|
||
let imported = 0;
|
||
let errors = 0;
|
||
|
||
const ripopola = true;
|
||
|
||
dataObjects = null;
|
||
|
||
let myarr = null;
|
||
|
||
try {
|
||
dataObjects = JSON.parse(`[${data.arrdata}]`);
|
||
|
||
myarr = dataObjects[0].item_list.item;
|
||
} catch (e) {
|
||
dataObjects = null;
|
||
}
|
||
|
||
if (myarr && ripopola) {
|
||
console.log('*** INIZIO IMPORT RIPOPOLAMENTO ... ', myarr.length);
|
||
|
||
// Cancella la collection ImportaMacros
|
||
await ImportaDescr.deleteMany({ idapp });
|
||
|
||
// Aggiungi i record su ImportaDescr
|
||
for (const recinv of myarr) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let recmacro = recinv;
|
||
|
||
recmacro.idapp = idapp;
|
||
|
||
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 };
|
||
|
||
try {
|
||
// non inserisce nuovi record, se non lo trova ! perché sono troppi !
|
||
let risrec = await ImportaDescr.findOneAndUpdate(
|
||
queryprod,
|
||
{ $set: recmacro },
|
||
{ new: true, upsert: true, strict: false }
|
||
);
|
||
if (risrec) {
|
||
imported++;
|
||
// if (imported > 1000)
|
||
// break;
|
||
if (imported % 100 === 0) console.log('importato ', imported, 'su ', myarr.length);
|
||
}
|
||
} catch (e) {
|
||
console.error(e);
|
||
errors++;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!myarr && ripopola) {
|
||
return res.status(400).send(data.arrdata);
|
||
}
|
||
|
||
// Rileggi tutti i record di ImportaDescr
|
||
dataObjects = await ImportaDescr.find({ idapp }).lean();
|
||
|
||
console.log('*** INIZIO IMPORT MACRO_DESCRELINKSITOWEB ... ');
|
||
|
||
let indprod = 0;
|
||
let newprod = 0;
|
||
|
||
let numprod = dataObjects.length;
|
||
|
||
for (const product of dataObjects) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let importa = true;
|
||
|
||
if (!product.code) importa = false;
|
||
|
||
if (importa) {
|
||
let productInfo = {
|
||
idapp: product.idapp,
|
||
code: product.code,
|
||
};
|
||
|
||
const myproduct = await Product.findOne({ 'productInfo.code': productInfo.code });
|
||
|
||
// IMPOSTA I VALORI SOLO SE NON ESISTONO ! ALTRIMENTI LASCIA QUELLI GIA' IMPORTATI (O MODIFICATI)
|
||
|
||
if (getvalueByJsonText(product.url)) {
|
||
if ((myproduct && !myproduct.productInfo.link_macro) || !myproduct.productInfo)
|
||
productInfo.link_macro = getvalueByJsonText(product.url);
|
||
}
|
||
if (getvalueByJsonText(product.descrizione)) {
|
||
if ((myproduct && !myproduct.productInfo.descrizione_breve_macro) || !myproduct.productInfo)
|
||
productInfo.descrizione_breve_macro = getvalueByJsonText(product.descrizione);
|
||
}
|
||
if (getvalueByJsonText(product.descrizione_completa)) {
|
||
if ((myproduct && !myproduct.productInfo.descrizione_completa_macro) || !myproduct.productInfo)
|
||
productInfo.descrizione_completa_macro = getvalueByJsonText(product.descrizione_completa);
|
||
}
|
||
if (getvalueByJsonText(product.sottotitolo)) {
|
||
if ((myproduct && !myproduct.productInfo.sottotitolo) || !myproduct.productInfo)
|
||
productInfo.sottotitolo = getvalueByJsonText(product.sottotitolo);
|
||
}
|
||
if (getvalueByJsonText(product.titolo)) {
|
||
if ((myproduct && !myproduct.productInfo.name) || !myproduct.productInfo)
|
||
productInfo.name = getvalueByJsonText(product.titolo);
|
||
}
|
||
|
||
const pagine = getvalueByJsonText(product.pagine);
|
||
|
||
let recisbn = {};
|
||
|
||
const trovato = await ImportaIsbn.findOne({ isbn: product.code }).lean();
|
||
if (trovato) {
|
||
// togli a recisbn l'_id
|
||
delete trovato._id;
|
||
recisbn = trovato;
|
||
}
|
||
|
||
if (pagine && pagine !== '0') {
|
||
recisbn.Pagine = pagine;
|
||
}
|
||
|
||
recisbn.link_macro = productInfo.link_macro;
|
||
recisbn.descrizione_breve_macro = productInfo.descrizione_breve_macro;
|
||
recisbn.descrizione_completa_macro = productInfo.descrizione_completa_macro;
|
||
recisbn.sottotitolo = productInfo.sottotitolo;
|
||
// recisbn.idapp = idapp;
|
||
|
||
try {
|
||
let risisbn = await ImportaIsbn.findOneAndUpdate(
|
||
{ isbn: product.code },
|
||
{ $set: recisbn },
|
||
{ new: true, upsert: true, strict: false }
|
||
);
|
||
|
||
// Update ProductInfo, non crea nuovi record !
|
||
let risrecInfo = await Product.findOneAndUpdate(
|
||
{ code: productInfo.code },
|
||
{ $set: productInfo },
|
||
{ new: true, upsert: false }
|
||
);
|
||
|
||
indprod++;
|
||
if (indprod % 100 === 0) console.log(indprod + '/' + numprod);
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
}
|
||
}
|
||
|
||
console.log(
|
||
'*** IMPORTATI: ',
|
||
imported,
|
||
'*** NUOVI: ',
|
||
newprod,
|
||
'AGGIORNATI = ' + updated + ' (su ' + dataObjects.length + ' RECORD)'
|
||
);
|
||
|
||
return res.status(200).send({ updated, imported, errors });
|
||
} else if (cmd === shared_consts.Cmd.MACRO_CATALOGO_JSON) {
|
||
try {
|
||
const macro = new Macro(idapp, { importadaFDV: true }); // Crea un'istanza della classe Macro
|
||
const result = await macro.importaCatalogo(data); // Chiama il metodo importaCatalogo
|
||
return res.status(200).send(result);
|
||
} catch (e) {
|
||
console.error(e.message);
|
||
return res.status(400).send(e);
|
||
}
|
||
} else if (cmd === shared_consts.Cmd.PRODUCTS) {
|
||
dataObjects = JSON.parse(`[${data.arrdata}]`);
|
||
|
||
let updated = 0;
|
||
let imported = 0;
|
||
let errors = 0;
|
||
|
||
for (const productImported of dataObjects) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let productInfo = {
|
||
idapp: productImported.idapp,
|
||
code: productImported.code,
|
||
name: productImported.name,
|
||
link: productImported.link,
|
||
idCatProds: [],
|
||
idSubCatProds: [],
|
||
// img: 'upload/products/' + product.code + '.jpg',
|
||
imagefile: productImported.code + '.jpg',
|
||
weight: productImported.weight,
|
||
unit: tools.getIdUnitsByText(productImported.unit),
|
||
productTypes: shared_consts.PRODUCTTYPE.PRODUCT,
|
||
};
|
||
|
||
let reccateg = null;
|
||
if (productImported.cat_name) {
|
||
arrcat = productImported.cat_name.trim().split(',');
|
||
for (const mycat of arrcat) {
|
||
let mycatstr = mycat.trim();
|
||
|
||
// Cerca la Categoria
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
if (!reccateg) {
|
||
// Non esiste questo produttore, quindi lo creo !
|
||
reccateg = new CatProd({ idapp, name: mycatstr });
|
||
ris = await reccateg.save();
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
}
|
||
|
||
if (reccateg) {
|
||
productInfo.idCatProds.push(reccateg._id);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (productImported.subcat_name) {
|
||
arrsubcat = productImported.subcat_name.trim().split(',');
|
||
productInfo.idSubCatProds = [];
|
||
for (const mysubcat of arrsubcat) {
|
||
let mysubcatstr = mysubcat.trim();
|
||
|
||
// Cerca la Sotto Categoria
|
||
let recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr }).lean();
|
||
if (!recsubcateg) {
|
||
// Non esiste questa Sotto Categoria, quindi la creo !
|
||
const idCatProd = reccateg ? reccateg._id : '';
|
||
recsubcateg = new SubCatProd({ idapp, name: mysubcatstr, idCatProd });
|
||
ris = await recsubcateg.save();
|
||
recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr, idCatProd }).lean();
|
||
}
|
||
|
||
if (recsubcateg) {
|
||
productInfo.idSubCatProds.push(recsubcateg._id);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!productImported.hasOwnProperty('active')) {
|
||
productImported.active = true;
|
||
}
|
||
|
||
/*if (product.code) delete product.code;
|
||
if (product.name) delete product.name;
|
||
if (product.link) delete product.link;*/
|
||
|
||
let esisteindb = await Product.findOne({ 'productInfo.code': productInfo.code }).lean();
|
||
|
||
// Update ProductInfo
|
||
let risrecInfo = await Product.findOneAndUpdate(
|
||
{ 'productInfo.code': productInfo.code },
|
||
{ $set: { productInfo: productInfo } },
|
||
{ new: true, upsert: true }
|
||
);
|
||
|
||
// .... ANDARE AVANTI DA QUI... .productInfo.... SISTEMARE!
|
||
|
||
if (risrecInfo) {
|
||
productImported.productInfo = risrecInfo._id;
|
||
|
||
recnewInfo = await Product.findOne({ code: product.code }).lean();
|
||
|
||
if (risrecInfo._id) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(productInfo, recnewInfo);
|
||
if (arrfieldchange && arrfieldchange.length > 0) {
|
||
// updated++;
|
||
console.log('Changed: ', recnewInfo.name + ': ' + arrfieldchange);
|
||
}
|
||
}
|
||
|
||
// Cerca il GAS
|
||
let recGas = null;
|
||
if (productImported.gas_name) {
|
||
// Cerca il GAS
|
||
recGas = await Gasordine.findOne({ idapp, name: productImported.gas_name }).lean();
|
||
}
|
||
|
||
if (!recGas && !!productImported.gas_name) {
|
||
recGas = new Gasordine({ idapp, name: productImported.gas_name, active: true });
|
||
// Non esiste questo GAS, quindi lo creo !
|
||
ris = await recGas.save();
|
||
recGas = await Gasordine.findOne({ idapp, name: productImported.gas_name }).lean();
|
||
}
|
||
|
||
let recProductExist = null;
|
||
let queryprod = { idProductInfo: productImported.idProductInfo };
|
||
|
||
if (recGas) {
|
||
queryprod = { ...queryprod, idGasordine: recGas._id };
|
||
}
|
||
|
||
recProductExist = await Product.findOne(queryprod).lean();
|
||
|
||
if (!recProductExist) {
|
||
isnuovo = true;
|
||
}
|
||
|
||
if (!options.aggiornaStockQty && esisteindb && !isnuovo) {
|
||
delete productImported.stockQty;
|
||
delete productImported.maxbookableGASQty;
|
||
}
|
||
|
||
// AGGIORNA PRODUCT
|
||
let risrec = await Product.findOneAndUpdate(queryprod, { $set: productImported }, { new: true, upsert: true });
|
||
|
||
let recnew = await Product.findOne(queryprod).lean();
|
||
|
||
if (risrec) {
|
||
if (risrec._id) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(productImported, recnew);
|
||
if (arrfieldchange.length > 0) {
|
||
updated++;
|
||
console.log('Changed:', productImported.idProductInfo + ': ' + arrfieldchange);
|
||
}
|
||
} else {
|
||
// Record didn't exist, so it was created
|
||
imported++;
|
||
}
|
||
} else {
|
||
// risrec is null or undefined, indicating an error
|
||
console.error('Error: ', productImported.productInfo.name);
|
||
errors++;
|
||
}
|
||
|
||
await Product.singlerecconvert_AfterImport_AndSave(idapp, recnew, isnuovo);
|
||
} else {
|
||
console.error('Error ProductInfo: ', productImported.code);
|
||
errors++;
|
||
}
|
||
}
|
||
|
||
return res.status(200).send({ updated, imported, errors });
|
||
} else if (cmd === shared_consts.Cmd.PRODUCTS_V2) {
|
||
let mydata = `[${data.arrdata}]`;
|
||
dataObjects = mydata.replace(/\n/g, '');
|
||
let arrrec = [];
|
||
try {
|
||
arrrec = JSON.parse(dataObjects);
|
||
} catch (e) {
|
||
console.error("Errore durante l'analisi del JSON:", e);
|
||
arrrec = [];
|
||
}
|
||
|
||
let updated = 0;
|
||
let imported = 0;
|
||
let errors = 0;
|
||
|
||
let ind = 0;
|
||
|
||
const [, ...myarrshift] = arrrec;
|
||
|
||
for (const rec of myarrshift) {
|
||
let risprod = await extractArrayDataFromCSV(idapp, rec);
|
||
let product = risprod.product;
|
||
let productInfo = risprod.productInfo;
|
||
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let reccateg = null;
|
||
if (rec.cat_name) {
|
||
arrcat = rec.cat_name.trim().split(',');
|
||
for (const mycat of arrcat) {
|
||
let mycatstr = mycat.trim();
|
||
|
||
// Cerca la Categoria
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
if (!reccateg) {
|
||
// Non esiste questo produttore, quindi lo creo !
|
||
reccateg = new CatProd({ idapp, name: mycatstr });
|
||
ris = await reccateg.save();
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
}
|
||
|
||
if (reccateg) {
|
||
productInfo.idCatProds.push(reccateg._id);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (rec.subcat_name) {
|
||
arrsubcat = rec.subcat_name.trim().split(',');
|
||
for (const mysubcat of arrsubcat) {
|
||
let mysubcatstr = mysubcat.trim();
|
||
|
||
// Cerca la Sotto Categoria
|
||
let recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr }).lean();
|
||
if (!recsubcateg) {
|
||
// Non esiste questa Sotto Categoria, quindi la creo !
|
||
const idCatProd = reccateg ? reccateg._id : '';
|
||
recsubcateg = new SubCatProd({ idapp, name: mysubcatstr, idCatProd });
|
||
ris = await recsubcateg.save();
|
||
recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr, idCatProd }).lean();
|
||
}
|
||
|
||
if (recsubcateg) {
|
||
productInfo.idSubCatProds.push(recsubcateg._id);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (!rec.hasOwnProperty('active')) {
|
||
product.active = true;
|
||
}
|
||
|
||
if (productInfo.productTypes.length === 1 && productInfo.productTypes[0] === undefined) {
|
||
productInfo.productTypes = [shared_consts.PRODUCTTYPE.PRODUCT];
|
||
}
|
||
|
||
let esisteindb = await Product.findOne({ code: productInfo.code }).lean();
|
||
|
||
// Update Product
|
||
let risrecInfo = await Product.findOneAndUpdate(
|
||
{ code: product.code },
|
||
{ $set: product },
|
||
{ new: true, upsert: true }
|
||
);
|
||
if (risrecInfo) {
|
||
recnewInfo = await Product.findOne({ code: product.code }).lean();
|
||
|
||
if (risrecInfo._id) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(productInfo, recnewInfo.productInfo);
|
||
if (arrfieldchange && arrfieldchange.length > 0) {
|
||
// updated++;
|
||
console.log('Changed: ', recnewInfo.name + ': ' + arrfieldchange);
|
||
}
|
||
}
|
||
|
||
// Cerca il GAS
|
||
let recGas = null;
|
||
if (rec.gas_name) {
|
||
// Cerca il GAS
|
||
recGas = await Gasordine.findOne({ idapp, name: rec.gas_name }).lean();
|
||
}
|
||
|
||
if (!recGas && !!rec.gas_name) {
|
||
recGas = new Gasordine({ idapp, name: rec.gas_name, active: true });
|
||
// Non esiste questo GAS, quindi lo creo !
|
||
ris = await recGas.save();
|
||
recGas = await Gasordine.findOne({ idapp, name: rec.gas_name }).lean();
|
||
}
|
||
|
||
if (recGas) {
|
||
if (rec.hasOwnProperty('note_ordine_gas')) {
|
||
const note_ordine_gas = rec['note_ordine_gas'];
|
||
await Gasordine.findOneAndUpdate({ _id: recGas._id }, { $set: { note_ordine_gas } });
|
||
}
|
||
}
|
||
|
||
let recProductExist = null;
|
||
let queryprod = { idProductInfo: product.idProductInfo };
|
||
|
||
if (recGas) {
|
||
queryprod = { ...queryprod, idGasordine: recGas._id };
|
||
}
|
||
|
||
recProductExist = await Product.findOne(queryprod).lean();
|
||
|
||
if (!recProductExist) {
|
||
isnuovo = true;
|
||
}
|
||
|
||
if (!options.aggiornaStockQty && esisteindb && !isnuovo) {
|
||
delete product.stockQty;
|
||
delete product.maxbookableGASQty;
|
||
}
|
||
|
||
// AGGIORNA PRODUCT
|
||
let risrec = await Product.findOneAndUpdate(queryprod, { $set: product }, { new: true, upsert: true });
|
||
|
||
let recnew = await Product.findOne(queryprod).lean();
|
||
|
||
if (risrec) {
|
||
if (risrec._id) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(product, recnew);
|
||
if (arrfieldchange.length > 0) {
|
||
updated++;
|
||
console.log('Changed: ', product.idProductInfo + ': ' + arrfieldchange);
|
||
}
|
||
} else {
|
||
// Record didn't exist, so it was created
|
||
imported++;
|
||
}
|
||
} else {
|
||
// risrec is null or undefined, indicating an error
|
||
console.error('Error: ', product.productInfo.name);
|
||
errors++;
|
||
}
|
||
|
||
await Product.singlerecconvert_AfterImport_AndSave(idapp, recnew, isnuovo);
|
||
} else {
|
||
console.error('Error ProductInfo: ', product.code);
|
||
errors++;
|
||
}
|
||
|
||
ind++;
|
||
}
|
||
|
||
// L'opzione ordered: false gestisce gli errori senza interrompere l'inserimento
|
||
/*return await Product.insertMany(dataObjects, { ordered: false })
|
||
.then((ris) => {
|
||
|
||
Product.convertAfterImportALLPROD(idapp, dataObjects).then((ris) => {
|
||
return res.status(200).send(true);
|
||
});
|
||
|
||
|
||
})
|
||
.catch((errors) => {
|
||
console.error(errors);
|
||
Product.convertAfterImportALLPROD(idapp).then((ris) => {
|
||
return res.status(200).send(true);
|
||
});
|
||
});*/
|
||
|
||
return res.status(200).send({ updated, imported, errors });
|
||
}
|
||
} catch (e) {
|
||
console.error('e', e);
|
||
return res.status(400).send();
|
||
}
|
||
|
||
return res.status(400).send();
|
||
});
|
||
|
||
/*
|
||
async function importaCatalogo(data) {
|
||
let updated = 0;
|
||
let imported = 0;
|
||
let errors = 0;
|
||
|
||
try {
|
||
const ripopola = true; //++MODIFICARE!
|
||
|
||
if (ripopola) {
|
||
dataObjects = null;
|
||
|
||
try {
|
||
dataObjects = JSON.parse(`[${data.arrdata}]`);
|
||
} catch (e) {
|
||
dataObjects = null;
|
||
}
|
||
|
||
if (dataObjects && dataObjects[0]) {
|
||
// Cancella la collection ImportaMacros
|
||
await Importamacro.deleteMany({ idapp });
|
||
|
||
// Aggiungi i record su ImportaMacros
|
||
for (const recinv of dataObjects[0]) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let recmacro = recinv;
|
||
|
||
recmacro.idapp = idapp;
|
||
|
||
recmacro._id = recmacro.id;
|
||
|
||
delete recmacro.id;
|
||
|
||
// Ottengo isbn e Pagine da ImportaIsbn
|
||
|
||
const recrankingisbn = await ImportaIsbn.findOne({ sku: recmacro.sku }).lean();
|
||
if (recrankingisbn) {
|
||
if (!recmacro.isbn) {
|
||
recmacro.isbn = recrankingisbn.isbn;
|
||
}
|
||
// Se Pagine non sono state settate
|
||
if ((!recmacro.Pagine || recmacro.Pagine === 0) && recrankingisbn.Pagine)
|
||
recmacro.Pagine = recrankingisbn.Pagine;
|
||
|
||
// Se misure non sono state settate
|
||
if (!recmacro.misure && recrankingisbn.misure) {
|
||
recmacro.misure = recrankingisbn.misure;
|
||
}
|
||
}
|
||
|
||
let queryprod = { idapp, _id: recmacro._id };
|
||
|
||
try {
|
||
let risrec = await Importamacro.findOneAndUpdate(
|
||
queryprod,
|
||
{ $set: recmacro },
|
||
{ new: true, upsert: true, strict: false }
|
||
);
|
||
if (risrec) {
|
||
imported++;
|
||
if (imported % 100 === 0) console.log('Importati su dir Temporanea ', imported);
|
||
}
|
||
} catch (e) {
|
||
console.error(e);
|
||
errors++;
|
||
}
|
||
}
|
||
}
|
||
|
||
const cancella_categorie = false;
|
||
|
||
if (cancella_categorie) {
|
||
await CatProd.deleteMany({ idapp });
|
||
}
|
||
}
|
||
|
||
// Rileggi tutti i record di ImportaMacros
|
||
dataObjects = await Importamacro.find({ idapp }).lean();
|
||
|
||
console.log('*** INIZIO IMPORT PRODOTTI ... ');
|
||
|
||
let indprod = 0;
|
||
let newprod = 0;
|
||
|
||
let numprod = dataObjects.length;
|
||
|
||
let nontrovati = 0;
|
||
|
||
for (const product of dataObjects) {
|
||
let isnuovo = false;
|
||
let setta = false;
|
||
|
||
let importa = true;
|
||
|
||
if (!product.title || !product.sku) importa = false;
|
||
|
||
if (importa) {
|
||
let versGM = product.Versione ? product.Versione : '';
|
||
|
||
// split versioneGM in array with separated ","
|
||
let arrversGM = versGM.split(',').map((x) => x.trim());
|
||
|
||
// se non esiste l'ISBN, allora me lo cerco in base a sku !
|
||
|
||
let trova = false;
|
||
if (product._id === '30310') {
|
||
trova = true;
|
||
}
|
||
|
||
if (!product.isbn || product.isbn.startsWith('field')) {
|
||
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}]`)
|
||
}
|
||
}
|
||
|
||
let productInfo = {
|
||
idapp: product.idapp,
|
||
code: product.isbn,
|
||
id_wp: product._id,
|
||
sku: product.sku,
|
||
|
||
name: product.title,
|
||
description: product.description,
|
||
short_descr: product.short_descr,
|
||
publisher: product.editore,
|
||
collezione: product.Collezione,
|
||
numCollana: product.numCollana,
|
||
// author: product.Autore ? product.Autore : '',
|
||
link: product.link ? product.link : '',
|
||
idCatProds: [],
|
||
idSubCatProds: [],
|
||
//img: 'upload/products/' + product.code + '.jpg',
|
||
// 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) {
|
||
productInfo.idCatProds = esisteindb.idCatProds;
|
||
productInfo.idSubCatProds = esisteindb.idSubCatProds;
|
||
}
|
||
|
||
let versione = 0;
|
||
|
||
if (indprod % 100 === 0) console.log(indprod + '/' + numprod);
|
||
|
||
productInfo.productTypes = [];
|
||
// console.log('indprod', indprod, 'arrversGM', arrversGM, 'versione', product.Versione);
|
||
|
||
// IdTipologia (Libri (1))
|
||
for (let i = 0; i < arrversGM.length; i++) {
|
||
// Download, DVD, Epub, Mobi, Nuovo, PDF, Streaming, Usato
|
||
if (arrversGM[i] === 'Nuovo') vers = shared_consts.PRODUCTTYPE.NUOVO;
|
||
else if (arrversGM[i] === 'Usato') vers = shared_consts.PRODUCTTYPE.USATO;
|
||
else if (arrversGM[i] === 'Download') vers = shared_consts.PRODUCTTYPE.DOWNLOAD;
|
||
else if (arrversGM[i] === 'DVD') vers = shared_consts.PRODUCTTYPE.DVD;
|
||
else if (arrversGM[i] === 'Epub') vers = shared_consts.PRODUCTTYPE.EPUB;
|
||
else if (arrversGM[i] === 'Mobi') vers = shared_consts.PRODUCTTYPE.MOBI;
|
||
else if (arrversGM[i] === 'PDF') vers = shared_consts.PRODUCTTYPE.PDF;
|
||
else if (arrversGM[i] === 'Streaming') vers = shared_consts.PRODUCTTYPE.STREAMING;
|
||
|
||
if (i === 0) {
|
||
// salvati il primo, // nel 99,9% dei casi c'è solo 1 elemento (perchè queste sono tutte le variazioni)
|
||
versione = vers;
|
||
}
|
||
|
||
productInfo.productTypes.push(vers);
|
||
}
|
||
|
||
|
||
productInfo.name = productInfo.name.replace(
|
||
/ - Usato$| - Nuovo$| - Epub$| - Ebook$| - Mobi$| - DVD$| - Streaming$| - Download$/,
|
||
''
|
||
);
|
||
|
||
const recrankingisbn = await ImportaIsbn.findOne({ sku: product.sku }).lean();
|
||
|
||
let reccateg = null;
|
||
|
||
if (product.categories) {
|
||
// Verifica prima se questa categoria è stata aggiornata !
|
||
if (recrankingisbn && recrankingisbn.DescrArgomento) {
|
||
if (tools.isArray(recrankingisbn.ListaArgomenti) && recrankingisbn.ListaArgomenti.length > 1) {
|
||
console.log('ListaArgomenti STA RITORNANDO UN ARRAY !!!! ', recrankingisbn.ListaArgomenti);
|
||
}
|
||
|
||
// !!!!
|
||
for (const idArgomento of recrankingisbn.ListaArgomenti) {
|
||
mycatstr = recrankingisbn.DescrArgomento;
|
||
|
||
if (mycatstr) productInfo = await updateProductInfo(productInfo, product, idapp, mycatstr);
|
||
}
|
||
} else {
|
||
arrcat = product.categories.trim().split(',');
|
||
productInfo.idCatProds = [];
|
||
for (const mycat of arrcat) {
|
||
let mycatstr = mycat.trim();
|
||
|
||
// Controlla se ci sono le sottocategorie:
|
||
arrsubcat = mycatstr.trim().split('>');
|
||
|
||
if (arrsubcat.length > 1) {
|
||
// Ci sono delle sottocategorie
|
||
mycatstr = arrsubcat[0].trim();
|
||
product.subcat_name = arrsubcat[1].trim();
|
||
}
|
||
|
||
// Cerca la Categoria
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
if (!reccateg) {
|
||
// Non esiste questo produttore, quindi lo creo !
|
||
reccateg = new CatProd({ idapp, name: mycatstr });
|
||
ris = await reccateg.save();
|
||
console.log('CREA con ARGOMENTO VECCHIO... ', mycatstr);
|
||
reccateg = await CatProd.findOne({ idapp, name: mycatstr }).lean();
|
||
}
|
||
|
||
if (reccateg) {
|
||
product.productInfo.idCatProds.push(reccateg._id);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// "Autore" : "Silia,Marucelli, Stefano,Cattinelli",
|
||
let arrAuthor = [];
|
||
if (product.Autore) {
|
||
const arrrecauthor = product.Autore.trim().split(',');
|
||
|
||
if (arrrecauthor.length >= 1) {
|
||
try {
|
||
let author = {
|
||
name: arrrecauthor[0].trim(),
|
||
};
|
||
if (arrrecauthor.length === 1) {
|
||
author = extractNameAndSurnameByComplete(arrrecauthor[0].trim());
|
||
} else {
|
||
author.surname = arrrecauthor[1].trim();
|
||
}
|
||
arrAuthor.push(author);
|
||
|
||
if (arrrecauthor.length > 1) {
|
||
for (let i = 2; i < arrrecauthor.length; i = i + 2) {
|
||
try {
|
||
author = {
|
||
name: arrrecauthor[i].trim(),
|
||
};
|
||
if (arrrecauthor.length > i + 1) {
|
||
author.surname = arrrecauthor[i + 1].trim();
|
||
}
|
||
arrAuthor.push(author);
|
||
} catch (e) {}
|
||
}
|
||
}
|
||
product.productInfo.idAuthors = [];
|
||
|
||
for (const myauthor of arrAuthor) {
|
||
// Cerca l'Autore
|
||
recauthor = await Author.findOne({ idapp, name: myauthor.name, surname: myauthor.surname }).lean();
|
||
if (!recauthor) {
|
||
// Non esiste questo Autore, quindi lo creo !
|
||
recauthor = new Author({ idapp, name: myauthor.name, surname: myauthor.surname });
|
||
ris = await recauthor.save();
|
||
recauthor = await Author.findOne({ idapp, name: myauthor.name, surname: myauthor.surname }).lean();
|
||
}
|
||
|
||
if (recauthor) {
|
||
product.productInfo.idAuthors.push(recauthor._id);
|
||
}
|
||
}
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
}
|
||
}
|
||
|
||
if (product.subcat_name) {
|
||
arrsubcat = product.subcat_name.trim().split(',');
|
||
product.productInfo.idSubCatProds = [];
|
||
for (const mysubcat of arrsubcat) {
|
||
let mysubcatstr = mysubcat.trim();
|
||
|
||
// Cerca la Sotto Categoria
|
||
let recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr }).lean();
|
||
if (!recsubcateg) {
|
||
// Non esiste questa Sotto Categoria, quindi la creo !
|
||
const idCatProd = reccateg ? reccateg._id : '';
|
||
recsubcateg = new SubCatProd({ idapp, name: mysubcatstr, idCatProd });
|
||
ris = await recsubcateg.save();
|
||
recsubcateg = await SubCatProd.findOne({ idapp, name: mysubcatstr, idCatProd }).lean();
|
||
}
|
||
|
||
if (recsubcateg) {
|
||
product.productInfo.idSubCatProds.push(recsubcateg._id);
|
||
}
|
||
}
|
||
}
|
||
if (product.productInfo.publisher) {
|
||
try {
|
||
publisher = product.productInfo.publisher.trim();
|
||
// Cerca la Sotto Categoria
|
||
let recpublisher = await Publisher.findOne({ idapp, name: publisher }).lean();
|
||
if (!recpublisher) {
|
||
// Non esiste questo Editore, quindi la creo !
|
||
recpublisher = new Publisher({ idapp, name: publisher });
|
||
ris = await recpublisher.save();
|
||
recpublisher = await Publisher.findOne({ idapp, name: publisher }).lean();
|
||
}
|
||
|
||
if (recpublisher) {
|
||
product.productInfo.idPublisher = recpublisher._id;
|
||
}
|
||
} catch (e) {
|
||
console.error(e);
|
||
}
|
||
}
|
||
// Aggiorna la collana solo se non è stata già impostata nel record attuale
|
||
//if (recproductInfoAttuale && !recproductInfoAttuale.idCollana && product.DescrizioneCollana) {
|
||
if (product.productInfo.collezione && product.productInfo.numCollana) {
|
||
reccollana = await Collana.findOne({ idapp, title: collezione }).lean();
|
||
if (!reccollana) {
|
||
try {
|
||
// Non esiste questa collana, quindi la creo !
|
||
reccollana = new Collana({ idapp, idCollana: product.productInfo.numCollana, title: product.DescrizioneCollana });
|
||
ris = await reccoll.save();
|
||
} catch (e) {
|
||
console.error('Err', e);
|
||
}
|
||
}
|
||
|
||
if (reccollana) product.productInfo.idCollana = reccollana._id;
|
||
}
|
||
|
||
if (!product.hasOwnProperty('active')) {
|
||
product.active = true;
|
||
}
|
||
|
||
// Update ProductInfo
|
||
let risrecInfo = await ProductInfo.findOneAndUpdate(
|
||
{ code: productInfo.code },
|
||
{ $set: productInfo },
|
||
{ new: true, upsert: true }
|
||
);
|
||
if (risrecInfo) {
|
||
product.idProductInfo = risrecInfo._id;
|
||
recnewInfo = await ProductInfo.findOne({ code: productInfo.code }).lean();
|
||
|
||
let { prodInfo, aggiornatoimg } = await downloadImgIfMissing(recnewInfo);
|
||
|
||
if (aggiornatoimg) {
|
||
await ProductInfo.findOneAndUpdate({ code: productInfo.code }, { $set: prodInfo });
|
||
}
|
||
|
||
if (risrecInfo._id) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(productInfo, recnewInfo);
|
||
if (arrfieldchange && arrfieldchange.length > 0) {
|
||
updated++;
|
||
console.log('Changed: ', recnewInfo.name + ': ' + arrfieldchange);
|
||
}
|
||
}
|
||
|
||
// 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 myproduct = {};
|
||
|
||
let recProductExist = null;
|
||
// ISBN e versione del prodotto sono le chiavi uniche
|
||
let queryprod = { idProductInfo: product.idProductInfo };
|
||
|
||
if (recGas) {
|
||
queryprod = { ...queryprod, idGasordine: recGas._id };
|
||
}
|
||
|
||
recProductExist = await Product.findOne(queryprod).lean();
|
||
|
||
if (!recProductExist) {
|
||
isnuovo = true;
|
||
}
|
||
|
||
let arrvariazioni = [];
|
||
if (isnuovo) {
|
||
myproduct.isbn = product.isbn;
|
||
myproduct.maxbookableGASQty = product.maxbookableGASQty ? product.maxbookableGASQty : null;
|
||
myproduct.active = product.active;
|
||
myproduct.idGasordine = recGas ? recGas._id : null;
|
||
myproduct.idProductInfo = product.idProductInfo;
|
||
myproduct.idapp = idapp;
|
||
} else {
|
||
arrvariazioni = recProductExist.arrvariazioni;
|
||
if (!arrvariazioni) {
|
||
arrvariazioni = [];
|
||
}
|
||
}
|
||
|
||
// cerca l'indice della versione in arrvariazioni
|
||
let ind = arrvariazioni.findIndex((x) => x.versione === versione);
|
||
|
||
let nuovaVariazione = ind < 0;
|
||
|
||
//
|
||
let variazione = {};
|
||
if (!nuovaVariazione) {
|
||
// Mantieni intatte questi campi del RECORD su DB:
|
||
variazione.quantita = arrvariazioni[ind].quantita;
|
||
}
|
||
|
||
// *** CONTROLLA SE AGGIORNARE O MENO DETERMINATI CAMPI CHE SONO STATI GIA' SETTATI
|
||
if (recrankingisbn) {
|
||
if (product.misure !== recrankingisbn.misure && recrankingisbn.misure) {
|
||
product.misure = recrankingisbn.misure;
|
||
}
|
||
if (product.formato !== recrankingisbn.formato && recrankingisbn.formato) {
|
||
product.formato = recrankingisbn.formato;
|
||
}
|
||
if (product.Pagine !== recrankingisbn.Pagine && recrankingisbn.Pagine) {
|
||
product.Pagine = recrankingisbn.Pagine;
|
||
}
|
||
if (product.Edizione !== recrankingisbn.Edizione && recrankingisbn.Edizione) {
|
||
product.Edizione = recrankingisbn.Edizione;
|
||
}
|
||
}
|
||
|
||
variazione.active = true; // ++ ??
|
||
variazione.versione = versione;
|
||
variazione.status = product.Stato ? product.Stato : null;
|
||
variazione.price = product.price ? parseFloat(tools.convertPriceEurToValue(product.price)) : null;
|
||
variazione.sale_price = product.sale_price
|
||
? parseFloat(tools.convertPriceEurToValue(product.sale_price))
|
||
: null;
|
||
variazione.formato = product.formato ? product.formato : '';
|
||
variazione.tipologia = product.Tipologia ? product.Tipologia : '';
|
||
variazione.edizione = product.Edizione ? product.Edizione : '';
|
||
variazione.pagine = tools.isValidNumber(product.Pagine) ? tools.convstrToInt(product.Pagine) : 0;
|
||
variazione.misure = product.misure ? product.misure : '';
|
||
variazione.eta = product.eta ? product.eta : '';
|
||
variazione.addtocart_link = product.addtocart_link ? product.addtocart_link : '';
|
||
|
||
if (!options.aggiornaStockQty && !nuovaVariazione) {
|
||
// non aggiornare la Quantita in magazzino
|
||
} else if (product.Quantita) {
|
||
variazione.quantita = parseInt(product.Quantita);
|
||
}
|
||
variazione.preOrderDate = product.preOrderDate ? product.preOrderDate : null;
|
||
|
||
// -----------------------------
|
||
|
||
if (ind >= 0) arrvariazioni[ind] = variazione; // aggiorna il record "ind" in arrvariazioni
|
||
else arrvariazioni.push(variazione); // aggiunge un nuovo record in arrvariazioni
|
||
|
||
// Effettua l'ordinamento seguendo la "versione"
|
||
arrvariazioni.sort((a, b) => a.versione - b.versione);
|
||
|
||
// Inserisce o aggiorna il record variazione nell'array delle variazioni, in base a "versione"
|
||
if (isnuovo) {
|
||
myproduct.arrvariazioni = arrvariazioni;
|
||
}
|
||
|
||
let recold = await Product.findOne(queryprod).lean();
|
||
|
||
let risrec = null;
|
||
if (isnuovo) {
|
||
// CREA PRODUCT
|
||
risrec = await Product.findOneAndUpdate(queryprod, { $set: myproduct }, { new: true, upsert: true });
|
||
} else {
|
||
// Esiste già, pertanto ci aggiorno arrvariazioni
|
||
risrec = await Product.findOneAndUpdate(
|
||
queryprod,
|
||
{ $set: { arrvariazioni } },
|
||
{ new: true, upsert: true }
|
||
);
|
||
}
|
||
|
||
let recnew = await Product.findOne(queryprod).lean();
|
||
|
||
if (risrec) {
|
||
if (risrec._id) {
|
||
if (recold) {
|
||
// Record existed, so it was updated
|
||
let arrfieldchange = tools.differentObjects(recold, recnew);
|
||
if (arrfieldchange.length > 0) {
|
||
updated++;
|
||
let modif = '';
|
||
for (const field of arrfieldchange) {
|
||
if (field === 'arrvariazioni') {
|
||
modif += field + ': ';
|
||
|
||
// Controlla quali campi sono variati tra recold.arrvariazioni e recnew.arrvariazioni
|
||
for (const variazione of recnew.arrvariazioni) {
|
||
// trova la versione in recold.arrvariazioni
|
||
let ind = recold.arrvariazioni.findIndex((x) => x.versione === variazione.versione);
|
||
|
||
if (ind < 0) {
|
||
modif +=
|
||
'Nuova Variazione [' +
|
||
variazione.versione +
|
||
'] ' +
|
||
variazione.status +
|
||
' | Price: ' +
|
||
variazione.price +
|
||
' -> Sale_Price: ' +
|
||
variazione.sale_price +
|
||
' | ';
|
||
} else {
|
||
let oldvariazione = recold.arrvariazioni[ind];
|
||
if (oldvariazione.status !== variazione.status) {
|
||
modif +=
|
||
'Variazione [' +
|
||
oldvariazione.versione +
|
||
'] ' +
|
||
variazione.status +
|
||
' -> ' +
|
||
variazione.status;
|
||
}
|
||
if (oldvariazione.price !== variazione.price) {
|
||
modif += ' | Price: ' + oldvariazione.price + ' -> ' + variazione.price;
|
||
}
|
||
if (oldvariazione.sale_price !== variazione.sale_price) {
|
||
modif += ' | Sale Price: ' + oldvariazione.sale_price + ' -> ' + variazione.sale_price;
|
||
}
|
||
if (oldvariazione.formato !== variazione.formato) {
|
||
modif += ' | Formato: ' + oldvariazione.formato + ' -> ' + variazione.formato;
|
||
}
|
||
if (oldvariazione.tipologia !== variazione.tipologia) {
|
||
modif += ' | Tipologia: ' + oldvariazione.tipologia + ' -> ' + variazione.tipologia;
|
||
}
|
||
if (oldvariazione.edizione !== variazione.edizione) {
|
||
modif += ' | Edizione: ' + oldvariazione.edizione + ' -> ' + variazione.edizione;
|
||
}
|
||
if (oldvariazione.eta !== variazione.eta) {
|
||
modif += ' | Età: ' + oldvariazione.eta + ' -> ' + variazione.eta;
|
||
}
|
||
if (oldvariazione.preOrderDate !== variazione.preOrderDate) {
|
||
modif +=
|
||
' | PreOrderDate: ' + oldvariazione.preOrderDate + ' -> ' + variazione.preOrderDate;
|
||
}
|
||
if (oldvariazione.addtocart_link !== variazione.addtocart_link) {
|
||
modif +=
|
||
' | AddToCart: ' + oldvariazione.addtocart_link + ' -> ' + variazione.addtocart_link;
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
modif += field + ': ' + recold[field] + ' -> ' + recnew[field] + ' | ';
|
||
}
|
||
}
|
||
|
||
console.log(
|
||
'Changed: [' + indprod + '/' + dataObjects.length + ']',
|
||
productInfo.name,
|
||
'[' + myproduct.idProductInfo + '] : ' + modif
|
||
);
|
||
}
|
||
} else {
|
||
newprod++;
|
||
console.log('Nuovo Prodotto : [' + newprod + '/' + dataObjects.length + ']', productInfo.name);
|
||
}
|
||
} else {
|
||
// Record didn't exist, so it was created
|
||
imported++;
|
||
}
|
||
} else {
|
||
// risrec is null or undefined, indicating an error
|
||
console.error('Error: ', myproduct.productInfo.name);
|
||
errors++;
|
||
}
|
||
|
||
await Product.singlerecconvert_AfterImport_AndSave(idapp, recnew, isnuovo);
|
||
} else {
|
||
console.error('Error ProductInfo: ', product.code);
|
||
errors++;
|
||
}
|
||
}
|
||
|
||
indprod++;
|
||
}
|
||
|
||
console.log(
|
||
'*** IMPORTATI: ',
|
||
imported,
|
||
'*** NUOVI: ',
|
||
newprod,
|
||
'AGGIORNATI = ' + updated + ' (su ' + dataObjects.length + ' RECORD)'
|
||
);
|
||
|
||
return res.status(200).send({ updated, imported, errors });
|
||
} catch (e) {
|
||
console.log(e.message);
|
||
return res.status(400).send(e);
|
||
}
|
||
}*/
|
||
|
||
router.post('/exec', authenticate, async (req, res) => {
|
||
try {
|
||
idapp = req.body.idapp;
|
||
console.log('/exec idapp=', idapp, req.body.script);
|
||
script = req.body.mydata.script;
|
||
listafiles = req.body.mydata.listafiles;
|
||
tokcheck = req.body.mydata.tokcheck;
|
||
extfiles = req.body.mydata.extfiles;
|
||
dir = req.body.mydata.dir;
|
||
withinput = req.body.mydata.withinput;
|
||
|
||
const TOKCHECK = 'php8.1_version_762321HSD121nJDokq@?!aFS.tar.gz';
|
||
|
||
if (!User.isAdmin(req.user.perm) || tokcheck !== TOKCHECK) {
|
||
// If without permissions, exit
|
||
return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
|
||
}
|
||
|
||
let result = '';
|
||
|
||
if (withinput) result = await tools.execScriptWithInputOnServer(idapp, script);
|
||
else result = await tools.execScriptOnServer(idapp, script, dir, listafiles, extfiles);
|
||
|
||
return res.send(result);
|
||
} catch (e) {
|
||
console.error('e', e);
|
||
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: '' });
|
||
}
|
||
});
|
||
|
||
router.post('/cloudflare', authenticate, async (req, res) => {
|
||
try {
|
||
idapp = req.body.idapp;
|
||
cmd = req.body.cmd;
|
||
tok = req.body.tok;
|
||
zoneId = req.body.zoneId;
|
||
tokcheck = req.body.tokcheck;
|
||
dnsRecordId = req.body.dnsRecordId;
|
||
record = req.body.record;
|
||
// console.log('/cloudflare idapp=', idapp, req.body.script);
|
||
|
||
const CloudFlareClass = require('../modules/Cloudflare');
|
||
|
||
const TOKCHECK = 'php8.1_version_762321HSD121nJDokq@?!aFS.tar.gz';
|
||
|
||
if (!User.isAdmin(req.user.perm) || tokcheck !== TOKCHECK) {
|
||
// If without permissions, exit
|
||
return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
|
||
}
|
||
|
||
let result = '';
|
||
|
||
let cf = new CloudFlareClass(null);
|
||
cf.init();
|
||
|
||
if (cmd === 'getzones') {
|
||
result = await cf.fetchCloudflareZones(tok);
|
||
} else if (cmd === 'getDNS') {
|
||
result = await cf.fetchDNSRecords(tok, zoneId);
|
||
} else if (cmd === 'setRecordDNS') {
|
||
result = await cf.updateDNSRecord(tok, zoneId, dnsRecordId, record);
|
||
} else if (cmd === 'delRecordDNS') {
|
||
result = await cf.deleteDNSRecord(tok, zoneId, dnsRecordId);
|
||
} else if (cmd === 'setCorrectIpsOnDNS') {
|
||
result = await cf.setCorrectIpsOnDNS(record);
|
||
} else if (cmd === 'gettok') {
|
||
result = process.env.CLOUDFLARE_TOKENS ? JSON.parse(process.env.CLOUDFLARE_TOKENS) : '';
|
||
}
|
||
|
||
return res.send(result);
|
||
} catch (e) {
|
||
console.error('e', e);
|
||
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: '' });
|
||
}
|
||
});
|
||
|
||
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;
|
||
cmd = req.body.cmd;
|
||
record = req.body.record;
|
||
tokcheck = req.body.tokcheck;
|
||
|
||
const MailinaboxClass = require('../modules/Mailinabox');
|
||
|
||
const TOKCHECK = 'php8.1_version_762321HSD121nJDokq@?!aFS.tar.gz';
|
||
|
||
if (!User.isAdmin(req.user.perm) || tokcheck !== TOKCHECK) {
|
||
// If without permissions, exit
|
||
return res.status(404).send({ code: server_constants.RIS_CODE_ERR_UNAUTHORIZED, msg: '' });
|
||
}
|
||
|
||
let result = '';
|
||
|
||
let miab = new MailinaboxClass(null);
|
||
miab.init();
|
||
|
||
if (cmd === 'getEmails') {
|
||
result = await miab.MIAB_getEmails(record);
|
||
} else if (cmd === 'removeEmails') {
|
||
result = await miab.removeEmail(record);
|
||
} else if (cmd === 'addEmail') {
|
||
result = await miab.addEmail(record);
|
||
} else if (cmd === 'setMailUserPassword') {
|
||
result = await miab.setMailUserPassword(record);
|
||
}
|
||
|
||
return res.send(result);
|
||
} catch (e) {
|
||
console.error('e', e);
|
||
return res.status(400).send({ code: server_constants.RIS_CODE_ERR, msg: '' });
|
||
}
|
||
});
|
||
|
||
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;
|