935 lines
36 KiB
JavaScript
935 lines
36 KiB
JavaScript
const server_constants = require('../tools/server_constants');
|
|
|
|
const shared_consts = require('../tools/shared_nodejs');
|
|
|
|
const tools = require('../tools/general');
|
|
|
|
const axios = require('axios');
|
|
|
|
const T_Web_Articoli = require('../models/t_web_articoli');
|
|
const T_Web_StatiProdotto = require('../models/t_web_statiprodotto');
|
|
const T_Web_TipiFormato = require('../models/t_web_tipiformato');
|
|
|
|
const SERVER_A_URL = process.env.SERVER_A_URL || "http://IP_DI_SERVER_A:3000";
|
|
const API_KEY = process.env.API_KEY_MSSQL;
|
|
|
|
const mongoose = require('mongoose').set('debug', false);
|
|
|
|
// Funzione per ottenere i dati
|
|
const getArticlesSales = async () => {
|
|
try {
|
|
const query = `
|
|
SELECT
|
|
a.IdArticolo, a.Titolo, a.DataPubblicazione, a.Ean13 AS isbn,
|
|
a.IdCollana, y.DescrizioneCollana, i2.DescrArgomento, a.ListaArgomenti,
|
|
a.Pagine, a.IdTipoFormato, a.Misure,
|
|
COALESCE(o.totVen, 0) as totVen, COALESCE(u.totFat, 0) as totFat,
|
|
COALESCE(p.rank3M, 0) as rank3M, COALESCE(t.fatrank3M, 0) as fatrank3M,
|
|
COALESCE(q.rank6M, 0) as rank6M, COALESCE(r.rank1Y, 0) as rank1Y,
|
|
COALESCE(t.fat3mesi, 0) as fatLast3M,
|
|
COALESCE(t2.fat6mesi, 0) as fatLast6M,
|
|
COALESCE(p.venduti3mesi, 0) as vLast3M,
|
|
COALESCE(q.venduti6mesi, 0) as vLast6M, COALESCE(r.venduti1anno, 0) as vLastY,
|
|
s.ultimoOrdine as dataUltimoOrdine
|
|
FROM T_WEB_Articoli a
|
|
LEFT JOIN (SELECT CodArticoloGM, SUM(Qta) as totVen FROM T_WEB_Ordini GROUP BY CodArticoloGM) o
|
|
ON a.IdArticolo = o.CodArticoloGM
|
|
LEFT JOIN (SELECT CodArticolo, SUM(TRY_CAST(Qta AS INT)) as totFat FROM T_WEB_ArticoliFatturati WHERE ISNUMERIC(Qta) = 1 GROUP BY CodArticolo) u
|
|
ON a.IdArticolo = u.CodArticolo
|
|
WHERE a.IdStatoProdotto IS NOT NULL
|
|
ORDER BY totVen DESC;
|
|
`;
|
|
|
|
const response = await axios.post(SERVER_A_URL + '/query', { query }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
|
|
return response.data || [];
|
|
|
|
} catch (error) {
|
|
console.error("Errore nel recupero degli articoli:", error);
|
|
throw new Error("Errore nel recupero degli articoli venduti.");
|
|
}
|
|
};
|
|
|
|
// Endpoint per ottenere i dati in formato JSON
|
|
exports.getArticlesSalesHandler = async (req, res) => {
|
|
try {
|
|
const data = await getArticlesSales();
|
|
if (!data.length) return res.status(404).json({ message: "Nessun articolo trovato." });
|
|
res.json(data);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
// Endpoint per esportare i dati come file JSON
|
|
exports.exportArticlesSalesByJSON = async (req, res) => {
|
|
try {
|
|
const data = await getArticlesSales();
|
|
if (!data.length) return res.status(404).json({ message: "Nessun articolo trovato." });
|
|
|
|
res.setHeader("Content-Type", "application/json");
|
|
res.setHeader("Content-Disposition", `attachment; filename="ranking_articles_${new Date().toISOString().split('T')[0]}.json"`);
|
|
res.json(data);
|
|
} catch (error) {
|
|
res.status(500).json({ error: error.message });
|
|
}
|
|
};
|
|
|
|
exports.getTableContent = async (options) => {
|
|
try {
|
|
// Chiama getTableContent, se ritorna errore hangup, allora attendi 2 secondi e poi richiamala.
|
|
const tableContent = await this.getTableContentBase(options);
|
|
return tableContent;
|
|
} catch (error) {
|
|
console.error('Error: ', error);
|
|
if (error.message === 'socket hang up') {
|
|
console.log('Error: hangup, waiting 2 seconds and retrying...');
|
|
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
return await this.getTableContent(options);
|
|
} else {
|
|
throw error;
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
exports.formatDate = (dateValue) => {
|
|
const date = new Date(dateValue);
|
|
const day = String(date.getDate()).padStart(2, '0');
|
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
|
const year = date.getFullYear();
|
|
return `${day}/${month}/${year}`;
|
|
};
|
|
|
|
exports.getModelByNameTable = (nameTable) => {
|
|
switch (nameTable) {
|
|
case 'T_Web_Articoli':
|
|
return T_Web_Articoli;
|
|
case 'T_Web_StatiProdotto':
|
|
return T_Web_StatiProdotto;
|
|
case 'T_Web_TipiFormato':
|
|
return T_Web_TipiFormato;
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
exports.getTableContentBase = async (options) => {
|
|
try {
|
|
// Verifica se la tabella esiste
|
|
const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
|
|
const checkResponse = await axios.post(SERVER_A_URL + '/query', { query: checkTableQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
if (!checkResponse?.data || checkResponse?.data.length === 0 || checkResponse?.data[0].tableExists === 0) {
|
|
return `La tabella '${options.nameTable}' non esiste.`;
|
|
}
|
|
|
|
// Recupera le colonne della tabella principale dal catalogo
|
|
const columnsQuery = `SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = '${options.nameTable}'`;
|
|
const columnsResponse = await axios.post(SERVER_A_URL + '/query', { query: columnsQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
const tableColumns = columnsResponse.data.map(col => col.COLUMN_NAME);
|
|
|
|
// Mappatura per unire i campi (ID e Descrizione)
|
|
const mergedMapping = {
|
|
"IdStatoProdotto": "DescrizioneStatoProdotto",
|
|
"IdTipologia": "DescrizioneTipologia",
|
|
"IdTipoFormato": "DescrizioneFormato",
|
|
"IdCollana": "DescrizioneCollana",
|
|
"ListaArgomenti": "DescrArgomento",
|
|
"ListaAutori": "AutoriCompleti",
|
|
"IdMarchioEditoriale": "CasaEditrice",
|
|
};
|
|
|
|
// Costruisce la query per recuperare i record
|
|
let dataQuery = "";
|
|
|
|
let records = [];
|
|
|
|
if (options?.usaDBGMLocale) {
|
|
|
|
// Cerca il modello corrispondente alla tabella se esiste
|
|
let mymodel = this.getModelByNameTable(options.nameTable);
|
|
if (!mymodel) {
|
|
// fai una query sul db locale mongodb dela tabella chiamata "options.nameTable"
|
|
mymodel = mongoose.model(options.nameTable, new mongoose.Schema({}, { strict: false }));
|
|
if (!mymodel)
|
|
return `Il modello per la tabella '${options.nameTable}' non esiste.`;
|
|
}
|
|
|
|
if (options.aggregation) {
|
|
records = await mymodel.aggregate(options.aggregation);
|
|
|
|
} else {
|
|
const pipeline = [];
|
|
|
|
// Filtro base se specificato
|
|
if (options.where) {
|
|
const whereConditions = options.where;
|
|
pipeline.push({ $match: whereConditions });
|
|
}
|
|
|
|
if (options.sort) {
|
|
pipeline.push({ $sort: options.sort });
|
|
}
|
|
|
|
if (options.limit) {
|
|
pipeline.push({ $limit: options.limit });
|
|
}
|
|
|
|
// Selezione dei campi
|
|
if (options.fieldGM) {
|
|
pipeline.push({ $project: { [options.fieldGM]: 1 } });
|
|
}
|
|
|
|
records = await mymodel.aggregate(pipeline);
|
|
}
|
|
|
|
console.log('results', records[0]);
|
|
|
|
} else {
|
|
|
|
let columnsToShow = 'T.*';
|
|
if (options.fieldGM) {
|
|
columnsToShow = 'T.' + options.fieldGM;
|
|
}
|
|
|
|
if (options.nameTable.toLowerCase() === 't_web_articoli') {
|
|
if (true) {
|
|
dataQuery = `
|
|
SELECT TOP ${options.numrec || 10000}
|
|
${columnsToShow}
|
|
` + (options.campispeciali ? `
|
|
,f.DescrizioneStatoProdotto
|
|
,i.DescrizioneTipologia
|
|
,n.DescrizioneFormato
|
|
,y.DescrizioneCollana
|
|
,z.AutoriCompleti
|
|
,i2.DescrArgomento
|
|
,z3.CasaEditrice` : ``) + (options.showQtaDisponibile ? ` ,q.QtaDisponibile ` : ``) +
|
|
` FROM T_WEB_Articoli T
|
|
JOIN(
|
|
SELECT IdArticolo, MAX(DataOra) AS data
|
|
FROM T_WEB_Articoli
|
|
GROUP BY IdArticolo
|
|
) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data `
|
|
+ (options.campispeciali ?
|
|
` LEFT JOIN(
|
|
SELECT e.IdStatoProdotto, e.Descrizione as DescrizioneStatoProdotto
|
|
FROM T_WEB_StatiProdotto e
|
|
JOIN(
|
|
SELECT IdStatoProdotto, MAX(DataOra) as data1
|
|
FROM T_WEB_StatiProdotto
|
|
GROUP BY IdStatoProdotto
|
|
) c ON e.IdStatoProdotto = c.IdStatoProdotto AND e.DataOra = c.data1
|
|
) f ON T.IdStatoProdotto = f.IdStatoProdotto
|
|
LEFT JOIN(
|
|
SELECT g.IdTipologia, g.Descrizione as DescrizioneTipologia
|
|
FROM T_WEB_Tipologie g
|
|
JOIN(
|
|
SELECT IdTipologia, MAX(DataOra) as data1
|
|
FROM T_WEB_Tipologie
|
|
GROUP BY IdTipologia
|
|
) h ON g.IdTipologia = h.IdTipologia AND g.DataOra = h.data1
|
|
) i ON T.IdTipologia = i.IdTipologia
|
|
LEFT JOIN(
|
|
SELECT l.IdTipoFormato, l.Descrizione as DescrizioneFormato
|
|
FROM T_WEB_TipiFormato l
|
|
JOIN(
|
|
SELECT IdTipoFormato, MAX(DataOra) as data1
|
|
FROM T_WEB_TipiFormato
|
|
GROUP BY IdTipoFormato
|
|
) m ON l.IdTipoFormato = m.IdTipoFormato AND l.DataOra = m.data1
|
|
) n ON T.IdTipoFormato = n.IdTipoFormato
|
|
LEFT JOIN(
|
|
SELECT v.IdCollana, v.Descrizione as DescrizioneCollana
|
|
FROM T_WEB_Collane v
|
|
INNER JOIN(
|
|
SELECT IdCollana, MAX(ID) as MaxID
|
|
FROM T_WEB_Collane
|
|
GROUP BY IdCollana
|
|
) x ON v.IdCollana = x.IdCollana AND v.ID = x.MaxID
|
|
) y ON T.IdCollana = y.IdCollana
|
|
LEFT JOIN(
|
|
SELECT g2.IdArgomento, g2.Descrizione as DescrArgomento
|
|
FROM T_WEB_Argomenti g2
|
|
INNER JOIN(
|
|
SELECT IdArgomento, MAX(DataOra) as data12
|
|
FROM T_WEB_Argomenti
|
|
GROUP BY IdArgomento
|
|
) h ON g2.IdArgomento = h.IdArgomento AND g2.DataOra = h.data12
|
|
) i2 ON T.ListaArgomenti = i2.IdArgomento
|
|
LEFT JOIN(
|
|
SELECT
|
|
T1.IdArticolo,
|
|
STUFF((
|
|
SELECT ',' + ISNULL(A2.AutoreCompleto, '')
|
|
FROM(
|
|
SELECT CAST('<root><x>' + REPLACE(T1.ListaAutori, ',', '</x><x>') + '</x></root>' AS XML) AS DataXML
|
|
) X
|
|
CROSS APPLY X.DataXML.nodes('/root/x') AS A(x)
|
|
CROSS APPLY(
|
|
SELECT TRY_CAST(LTRIM(RTRIM(A.x.value('.', 'VARCHAR(100)'))) AS INT) AS AutoreID
|
|
) CA
|
|
JOIN(
|
|
SELECT a.IdAutore, CONCAT(a.Nome, ' ', a.Cognome) AS AutoreCompleto
|
|
FROM T_WEB_Autori a
|
|
JOIN(
|
|
SELECT IdAutore, MAX(DataOra) AS maxData
|
|
FROM T_WEB_Autori
|
|
GROUP BY IdAutore
|
|
) aa ON a.IdAutore = aa.IdAutore AND a.DataOra = aa.maxData
|
|
) A2 ON CA.AutoreID = A2.IdAutore
|
|
FOR XML PATH(''), TYPE
|
|
).value('.', 'NVARCHAR(MAX)'), 1, 1, '') AS AutoriCompleti
|
|
FROM T_WEB_Articoli T1
|
|
GROUP BY T1.IdArticolo, T1.ListaAutori
|
|
) z ON T.IdArticolo = z.IdArticolo
|
|
LEFT JOIN(
|
|
SELECT a3.IdMarchioEditoriale, a3.Descrizione as CasaEditrice
|
|
FROM T_WEB_MarchiEditoriali a3
|
|
JOIN(
|
|
SELECT IdMarchioEditoriale, MAX(DataOra) as maxData
|
|
FROM T_WEB_MarchiEditoriali
|
|
GROUP BY IdMarchioEditoriale
|
|
) aa3 ON a3.IdMarchioEditoriale = aa3.IdMarchioEditoriale AND a3.DataOra = aa3.maxData
|
|
) z3 ON T.IdMarchioEditoriale = z3.IdMarchioEditoriale `
|
|
: ``)
|
|
+ (options.showQtaDisponibile ?
|
|
` LEFT JOIN(
|
|
SELECT o.Codice, o.QtaDisponibile
|
|
FROM T_WEB_Disponibile o
|
|
JOIN(
|
|
SELECT Codice, MAX(DataOra) as data1
|
|
FROM T_WEB_Disponibile
|
|
GROUP BY Codice
|
|
) p ON o.Codice = p.Codice AND o.DataOra = p.data1
|
|
) q ON T.IdArticolo = q.Codice` : ``)
|
|
} else {
|
|
dataQuery += `
|
|
SELECT TOP ${options.numrec}
|
|
T.*
|
|
FROM T_WEB_Articoli T
|
|
JOIN(
|
|
SELECT IdArticolo, MAX(DataOra) AS data
|
|
FROM T_WEB_Articoli
|
|
GROUP BY IdArticolo
|
|
) b ON T.IdArticolo = b.IdArticolo AND T.DataOra = b.data
|
|
`;
|
|
}
|
|
} else {
|
|
dataQuery = `SELECT TOP ${options.numrec || 10000} * FROM ${options.nameTable} `;
|
|
}
|
|
if (options.where && options.where.trim() !== "") {
|
|
dataQuery += ` WHERE ${options.where} `;
|
|
}
|
|
|
|
console.log('dataQuery', dataQuery);
|
|
|
|
// Esegue la query per recuperare i dati
|
|
// console.log('dataQuery', dataQuery);
|
|
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
|
|
records = dataResponse?.data;
|
|
}
|
|
|
|
if (!records || records.length === 0) {
|
|
return [];
|
|
}
|
|
|
|
// Determina quali colonne visualizzare.
|
|
let displayColumns;
|
|
if (options.nameTable.toLowerCase() === 't_web_articoli') {
|
|
// Usa tutte le proprietà del record, escludendo le colonne dei campi uniti (quelle usate per il merge)
|
|
displayColumns = Object.keys(records[0]).filter(col => !Object.values(mergedMapping).includes(col));
|
|
} else {
|
|
displayColumns = tableColumns;
|
|
}
|
|
|
|
// Funzione per ottenere il valore da visualizzare, fondendo i campi se presente nella mappatura
|
|
const getDisplayValue = (record, col) => {
|
|
let value = record[col] ?? 'NULL';
|
|
// Format date solo se il nome della colonna indica una data/ora
|
|
if ((col.toLowerCase().includes("data") || col.toLowerCase().includes("ora")) && value !== 'NULL') {
|
|
if (value.includes(',')) {
|
|
// Se ci sono più valori separati da virgola, formatta ciascuno se è una data valida
|
|
value = value.split(',')
|
|
.map(item => {
|
|
const trimmed = item.trim();
|
|
const parsed = Date.parse(trimmed);
|
|
return !isNaN(parsed) ? this.formatDate(trimmed) : trimmed;
|
|
})
|
|
.join(', ');
|
|
} else {
|
|
const parsed = Date.parse(value);
|
|
if (!isNaN(parsed)) {
|
|
value = this.formatDate(value);
|
|
}
|
|
}
|
|
}
|
|
if (mergedMapping[col]) {
|
|
return `${record[mergedMapping[col]] || ''} (${value})`;
|
|
}
|
|
return value;
|
|
};
|
|
|
|
// Costruisce l'output HTML
|
|
let output = "";
|
|
if (options.outhtml) {
|
|
if (records.length === 1) {
|
|
// Se c'è un solo record, visualizza una lista di chiavi e valori
|
|
const record = records[0];
|
|
output += `
|
|
<table border='1' style="border-collapse: collapse;" >
|
|
<thead>
|
|
<tr>
|
|
<th style="padding: 8px; background-color: #f2f2f2;">Campo</th>
|
|
<th style="padding: 8px; background-color: #f2f2f2;">Valore</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
`;
|
|
displayColumns.forEach(column => {
|
|
output += `
|
|
<tr>
|
|
<td style="padding: 8px;">${column}</td>
|
|
<td style="padding: 8px;">${getDisplayValue(record, column)}</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
output += `
|
|
</tbody>
|
|
</table>
|
|
`;
|
|
} else {
|
|
// Se ci sono più record, visualizza una tabella con intestazioni
|
|
output += "<table border='1' style='border-collapse: collapse; width: 100%;'><thead><tr>";
|
|
displayColumns.forEach(column => {
|
|
output += `< th style = "padding: 8px; background-color: #f2f2f2;" > ${column}</th > `;
|
|
});
|
|
output += "</tr></thead><tbody>";
|
|
records.forEach(record => {
|
|
output += "<tr>";
|
|
displayColumns.forEach(column => {
|
|
output += `< td style = "padding: 8px;" > ${getDisplayValue(record, column)}</td > `;
|
|
});
|
|
output += "</tr>";
|
|
});
|
|
output += "</tbody></table>";
|
|
}
|
|
} else {
|
|
// solo dati
|
|
output = {};
|
|
|
|
if (options.fieldGM) {
|
|
if (records && records.length === 1) {
|
|
output[options.fieldGM] = records[0][options.fieldGM];
|
|
}
|
|
} else {
|
|
output = [];
|
|
records.forEach(record => {
|
|
let myrec = {}
|
|
|
|
if (options.recordraw) {
|
|
myrec = record;
|
|
} else {
|
|
|
|
displayColumns.forEach(column => {
|
|
const value = record[column];
|
|
if (value !== undefined && value !== null) {
|
|
const type = typeof value;
|
|
if (type === 'number' && !mergedMapping[column]) {
|
|
myrec[column] = value;
|
|
} else if (type === 'boolean') {
|
|
myrec[column] = value;
|
|
} else if (value instanceof Date) {
|
|
myrec[column] = this.formatDate(value);
|
|
} else {
|
|
myrec[column] = `${getDisplayValue(record, column)}`.trim();
|
|
}
|
|
}
|
|
});
|
|
}
|
|
output.push(myrec)
|
|
});
|
|
}
|
|
}
|
|
return output;
|
|
|
|
} catch (error) {
|
|
output = `${error?.response?.data?.error || error?.stack || error.message}`;
|
|
console.error("Errore nel recupero della tabella: ", `${error.response.data.error || error.stack || error.message}`);
|
|
if (options.outhtml) {
|
|
output = `
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Errore nel Recupero della Tabella ${options.nameTable}</title>
|
|
<style>
|
|
body {
|
|
font - family: Arial, sans-serif;
|
|
background-color: #f7f7f7;
|
|
color: #333;
|
|
padding: 20px;
|
|
}
|
|
.error-container {
|
|
background - color: #ffe6e6;
|
|
border: 1px solid #ff4d4d;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
max-width: 800px;
|
|
margin: auto;
|
|
}
|
|
.error-title {
|
|
font - size: 24px;
|
|
font-weight: bold;
|
|
color: #d8000c;
|
|
margin-bottom: 10px;
|
|
}
|
|
.error-message {
|
|
font - size: 16px;
|
|
white-space: pre-wrap;
|
|
background: #fff;
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 3px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="error-container">
|
|
<div class="error-title">Errore nel Recupero della Tabella ${options.nameTable} con query: ${options.where}</div>
|
|
<div class="error-message">
|
|
${error.response.data.error || error.stack || error.message}
|
|
</div>
|
|
</div>
|
|
</body>
|
|
`;
|
|
}
|
|
return output;
|
|
// throw new Error("Errore nel recupero della tabella.");
|
|
}
|
|
};
|
|
|
|
const setTableContent = async (options) => {
|
|
try {
|
|
// checkPermissions()
|
|
|
|
const esegui = true
|
|
|
|
if (esegui) {
|
|
|
|
// Verifica se la tabella esiste
|
|
const checkTableQuery = `SELECT COUNT(*) as tableExists FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '${options.nameTable}'`;
|
|
const checkResponse = await axios.post(SERVER_A_URL + '/query', { query: checkTableQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
|
|
if (!checkResponse.data || checkResponse.data.length === 0 || checkResponse.data[0].tableExists === 0) {
|
|
return `La tabella '${options.nameTable}' non esiste.`;
|
|
}
|
|
|
|
// Costruisce la query per inserire o aggiornare i record
|
|
let dataQuery = "";
|
|
if (options.insertMode) {
|
|
// Modalità INSERT
|
|
const columns = Object.keys(options.data);
|
|
const values = columns.map(col => `'${options.data[col]}'`).join(", ");
|
|
dataQuery = `
|
|
INSERT INTO ${options.nameTable} (${columns.join(", ")})
|
|
VALUES (${values});
|
|
`;
|
|
} else {
|
|
// Modalità UPDATE
|
|
const updateFields = Object.keys(options.data)
|
|
.map(col => `${col} = '${options.data[col]}'`)
|
|
.join(", ");
|
|
const whereClause = options.where ? `WHERE ${options.where}` : "";
|
|
dataQuery = `
|
|
UPDATE ${options.nameTable}
|
|
SET ${updateFields}
|
|
${whereClause};
|
|
`;
|
|
}
|
|
|
|
console.log('dataQuery', dataQuery);
|
|
|
|
// Esegue la query per inserire o aggiornare i dati
|
|
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
|
|
if (dataResponse.data && dataResponse.data.affectedRows > 0) {
|
|
return `Operazione completata con successo su '${options.nameTable}'.`;
|
|
} else {
|
|
return `Nessun record modificato nella tabella '${options.nameTable}'.`;
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error("Errore nell'inserimento o aggiornamento della tabella: ", error.message);
|
|
if (options.outhtml) {
|
|
output = `
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background-color: #f7f7f7;
|
|
color: #333;
|
|
padding: 20px;
|
|
}
|
|
.error-container {
|
|
background-color: #ffe6e6;
|
|
border: 1px solid #ff4d4d;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
max-width: 800px;
|
|
margin: auto;
|
|
}
|
|
.error-title {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #d8000c;
|
|
margin-bottom: 10px;
|
|
}
|
|
.error-message {
|
|
font-size: 16px;
|
|
white-space: pre-wrap;
|
|
background: #fff;
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 3px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="error-container">
|
|
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</div>
|
|
<div class="error-message">
|
|
${error.response.data.error || error.stack || error.message}
|
|
</div>
|
|
</div>
|
|
</body>
|
|
`;
|
|
return output;
|
|
}
|
|
return "Errore nell'inserimento o aggiornamento della tabella.";
|
|
}
|
|
};
|
|
const checkPermissions = async (options) => {
|
|
try {
|
|
const dataQuery = `
|
|
SELECT
|
|
dp.name AS UserName,
|
|
dp.type_desc AS UserType,
|
|
o.name AS ObjectName,
|
|
p.permission_name,
|
|
p.state_desc AS PermissionState
|
|
FROM
|
|
sys.database_permissions p
|
|
JOIN
|
|
sys.objects o ON p.major_id = o.object_id
|
|
JOIN
|
|
sys.database_principals dp ON p.grantee_principal_id = dp.principal_id
|
|
WHERE
|
|
o.name = 'T_WEB_Articoli';
|
|
`;
|
|
|
|
console.log('checkPermissions query:', dataQuery);
|
|
|
|
// Esegue la query per inserire o aggiornare i dati
|
|
const dataResponse = await axios.post(SERVER_A_URL + '/query', { query: dataQuery }, {
|
|
headers: { 'x-api-key': API_KEY }
|
|
});
|
|
|
|
console.log('checkPermissions result:', dataResponse.data);
|
|
|
|
if (dataResponse.data && dataResponse.data.affectedRows > 0) {
|
|
return `Operazione completata con successo.`;
|
|
} else {
|
|
return `Nessun permesso.`;
|
|
}
|
|
} catch (error) {
|
|
console.error("Errore nel check dei Permessi: ", error.message);
|
|
if (options.outhtml) {
|
|
output = `
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</title>
|
|
<style>
|
|
body {
|
|
font-family: Arial, sans-serif;
|
|
background-color: #f7f7f7;
|
|
color: #333;
|
|
padding: 20px;
|
|
}
|
|
.error-container {
|
|
background-color: #ffe6e6;
|
|
border: 1px solid #ff4d4d;
|
|
padding: 20px;
|
|
border-radius: 5px;
|
|
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
|
max-width: 800px;
|
|
margin: auto;
|
|
}
|
|
.error-title {
|
|
font-size: 24px;
|
|
font-weight: bold;
|
|
color: #d8000c;
|
|
margin-bottom: 10px;
|
|
}
|
|
.error-message {
|
|
font-size: 16px;
|
|
white-space: pre-wrap;
|
|
background: #fff;
|
|
padding: 10px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 3px;
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="error-container">
|
|
<div class="error-title">Errore nell'inserimento o aggiornamento della Tabella ${options.nameTable}</div>
|
|
<div class="error-message">
|
|
${error.response.data.error || error.stack || error.message}
|
|
</div>
|
|
</div>
|
|
</body>
|
|
`;
|
|
return output;
|
|
}
|
|
return "Errore nell'inserimento o aggiornamento della tabella.";
|
|
}
|
|
};
|
|
|
|
// Endpoint per mostrare i dati della tabella
|
|
exports.viewTable = async (req, res) => {
|
|
try {
|
|
const options = req.body.options;
|
|
const tableContent = await this.getTableContent(options);
|
|
|
|
let out = {};
|
|
|
|
if (options.outhtml) {
|
|
out = `
|
|
<h2 class="text-center">Tabella: ${options.nameTable}</h2>
|
|
<div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
|
|
<div class="row justify-center">
|
|
${tableContent}
|
|
</div>
|
|
`
|
|
} else {
|
|
out = tableContent;
|
|
}
|
|
|
|
if (tableContent && tableContent.length > 0) {
|
|
if (options.updatelocaldb) {
|
|
this.updateLocalDb(tableContent[0], options)
|
|
}
|
|
}
|
|
|
|
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
|
|
|
|
} catch (error) {
|
|
console.error('Error: ', error);
|
|
return res.send({ code: server_constants.RIS_CODE_ERR, error });
|
|
}
|
|
};
|
|
|
|
exports.updateLocalDb = async (tableContent, options) => {
|
|
try {
|
|
|
|
const ProductInfo = require('../models/productInfo');
|
|
const CatProd = require('../models/catprod');
|
|
|
|
let recproductInfo = {
|
|
code: tableContent.Ean13.trim(),
|
|
};
|
|
|
|
let risrecUpdated = null;
|
|
|
|
const recfound = await ProductInfo.findOne({ code: recproductInfo.code }).lean();
|
|
if (recfound) {
|
|
|
|
ListaArgomenti = tableContent.ListaArgomenti;
|
|
|
|
let arrayPulito = ListaArgomenti
|
|
.trim() // Rimuove gli spazi all'inizio e alla fine
|
|
.replace(/[\(\)]/g, '') // Rimuove le parentesi tonde
|
|
.split(','); // Divide la stringa in un array usando la virgola come separatore
|
|
|
|
if (arrayPulito && arrayPulito.length > 0) {
|
|
let aggiornacat = false;
|
|
const precCatProds = recfound.idCatProds;
|
|
let reccatprods = [];
|
|
for (let i = 0; i < arrayPulito.length; i++) {
|
|
const idArgomento = parseInt(arrayPulito[i]);
|
|
reccateg = await CatProd.findOne({ idArgomento }).lean();
|
|
|
|
if (reccateg) {
|
|
// aggiungi solo se non esiste già
|
|
if (!reccatprods.includes(reccateg._id)) {
|
|
reccatprods.push(reccateg._id);
|
|
}
|
|
}
|
|
}
|
|
|
|
// ora controlla se l'array reccatprods e' diverso da precCatProds
|
|
if (reccatprods.length !== precCatProds.length) {
|
|
aggiornacat = true;
|
|
} else {
|
|
for (let i = 0; i < reccatprods.length; i++) {
|
|
if (reccatprods[i].toString() !== precCatProds[i].toString()) {
|
|
aggiornacat = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (aggiornacat) {
|
|
recproductInfo.idCatProds = reccatprods;
|
|
aggiorna = true;
|
|
}
|
|
}
|
|
|
|
if (tableContent.DataPubblicazione.trim()) {
|
|
recproductInfo.date_pub = new Date(tools.convertiDataItaliana(tableContent.DataPubblicazione.trim()).date);
|
|
// convert data to timestamp
|
|
recproductInfo.date_pub_ts = recproductInfo.date_pub.getTime();
|
|
aggiorna = true;
|
|
}
|
|
|
|
if (aggiorna) {
|
|
risrecUpdated = await ProductInfo.findOneAndUpdate({ code: recproductInfo.code }, { $set: recproductInfo }, { new: true, upsert: true });
|
|
}
|
|
|
|
return risrecUpdated;
|
|
}
|
|
|
|
} catch (e) {
|
|
console.error('Error: ', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Endpoint per mostrare i dati della tabella
|
|
exports.queryTable = async (req, res) => {
|
|
try {
|
|
const options = req.body.options;
|
|
const tableContent = await this.getTableContent(options);
|
|
|
|
let out = {};
|
|
|
|
if (options.outhtml) {
|
|
out = `
|
|
<h2>Tabella: ${options.nameTable}</h2>
|
|
<div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
|
|
${tableContent}
|
|
`
|
|
} else {
|
|
out = tableContent;
|
|
}
|
|
|
|
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
|
|
|
|
} catch (error) {
|
|
console.error('Error: ', error);
|
|
return res.send({ code: server_constants.RIS_CODE_ERR, error });
|
|
}
|
|
};
|
|
// Endpoint per salvare i dati di una tabella
|
|
exports.saveTable = async (req, res) => {
|
|
try {
|
|
const options = req.body.options;
|
|
const tableContent = await setTableContent(options);
|
|
|
|
let out = {};
|
|
|
|
if (options.outhtml) {
|
|
out = `
|
|
<h2 class="text-center">Tabella: ${options.nameTable}</h2>
|
|
<div class="text-h7 row justify-center text-blue">Query: ${options.where}<br></div>
|
|
<div class="row justify-center">
|
|
${tableContent}
|
|
</div>
|
|
`
|
|
} else {
|
|
out = tableContent;
|
|
}
|
|
|
|
return res.send({ code: server_constants.RIS_CODE_OK, data: out });
|
|
|
|
} catch (error) {
|
|
console.error('Error: ', error);
|
|
return res.send({ code: server_constants.RIS_CODE_ERR, error });
|
|
}
|
|
};
|
|
|
|
exports.mssqlmigrateTables = async (req) => {
|
|
const MssqlMigrator = require('../modules/MssqlMigrator'); // Importa la classe Macro
|
|
|
|
try {
|
|
const options = req.body.options;
|
|
let listaTabelle = [];
|
|
|
|
if (options?.tutte) {
|
|
// const listaTabelle = ['T_WEB_StatiProdotto'];
|
|
listaTabelle = ['T_WEB_TitoliOriginali', 'T_WEB_TestateOrdini', 'T_WEB_Ordini', 'T_WEB_Disponibile', 'T_WOO_TestateOrdini', 'T_WOO_Ordini', 'T_WEB_Articoli',
|
|
'T_WEB_Argomenti', 'T_WEB_ClientiInternet', 'T_WOO_Clienti', 'T_WEB_Autori', 'T_WEB_Collane', 'T_WEB_MarchiEditoriali', 'T_WEB_StatiProdotto', 'T_WEB_TipiFormato', 'T_WEB_Tipologie', 'T_WEB_ArticoliFatturati', 'T_WEB_IdInternetFatturati',
|
|
'T_WEB_Edizioni', 'T_WEB_Contratti'];
|
|
} else {
|
|
listaTabelle = ['T_WEB_Articoli', 'T_WEB_ArticoliFatturati'];
|
|
}
|
|
|
|
const migrator = new MssqlMigrator();
|
|
return await migrator.migrateTables(listaTabelle);
|
|
|
|
} catch (e) {
|
|
console.error(e.message);
|
|
return 'Errore: ' + e.message
|
|
}
|
|
|
|
};
|
|
exports.updateAllBook = async (idapp, options) => {
|
|
|
|
const Macro = require('../modules/Macro'); // Importa la classe Macro
|
|
|
|
try {
|
|
const macro = new Macro(idapp); // Crea un'istanza della classe Macro
|
|
options.idapp = idapp;
|
|
|
|
return await macro.updateLocalDbFromGM_T_Web_Articoli(options);
|
|
|
|
} catch (e) {
|
|
console.error(e.message);
|
|
throw e;
|
|
}
|
|
};
|
|
|
|
exports.updateAllBookRoute = async (req, res) => {
|
|
|
|
try {
|
|
const idapp = req.body.idapp;
|
|
const options = req.body.options;
|
|
const result = await this.updateAllBook(idapp, options);
|
|
|
|
return res.status(200).send({ data: result });
|
|
|
|
} catch (e) {
|
|
console.error(e.message);
|
|
if (res) {
|
|
return res.status(400).send(e);
|
|
}
|
|
}
|
|
}
|