- miglioramenti ricerca titoli e modifica del trafiletto

- miglior visualizzazione delle liste
This commit is contained in:
Surya Paolo
2025-04-30 13:27:54 +02:00
parent 3d4f8b0d04
commit e40fbd550b
12 changed files with 277 additions and 134 deletions

View File

@@ -29,7 +29,7 @@ const getArticlesSales = async () => {
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,
COALESCE(q.venduti6mesi, 0) as vLast6M, COALESCE(r.venduti1anno, 0) as vLast1Y,
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

View File

@@ -28,13 +28,21 @@ const CatalogSchema = new Schema({
type: String,
},
foto_collana: IImg,
idCollane: [{
type: String,
}],
argomenti: [{
type: String,
}],
condition_andor: {
type: Number,
default: 0,
},
editore: [{ type: String }],
descr_introduttiva: {
type: String,
},

View File

@@ -126,6 +126,11 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) {
$project: {
_id: 1,
name: 1,
idArgomento: 1,
descr_estesa: 1,
img: 1,
icon: 1,
color: 1,
quanti: { $size: '$myproducts' }, // Conta il numero di prodotti per ciascun CatProd
products: {
$map: {

View File

@@ -52,6 +52,64 @@ module.exports.findAllIdApp = async function (idapp) {
return await Collana.find(myfind).sort({title: 1}).lean();
};
module.exports.getCollaneWithTitleCount = async function (idapp) {
try {
const myquery = [
{ $match: { idapp } },
{
$lookup: {
from: 'productinfos', // Nome della tua collezione productInfo
localField: '_id',
foreignField: 'idCollana',
as: 'products'
}
},
{
$addFields: {
myproducts: {
$filter: {
input: "$products",
as: "prod",
cond: {
$in: ["$$prod.idStatoProdotto", [1, 4, 34, 45, 46]]
}
}
}
}
}, {
$project: {
_id: 1,
title: 1,
idCollana: 1,
dataOra: 1,
quanti: { $size: '$myproducts' },
products: {
$map: {
input: "$myproducts",
as: "prod",
in: {
name: "$$prod.name"
}
}
}
}
},
{ $match: { quanti: { $gt: 0 } } }, // esclude i record con quanti = 0
{ $sort: { title: 1 } } // Ordina i risultati per nome
];
const result = await Collana.aggregate(myquery);
return result;
} catch (error) {
console.error('Error retrieving idCollana with title count:', error);
throw error;
}
}
module.exports.createIndexes()
.then(() => { })
.catch((err) => { throw err; });

View File

@@ -133,7 +133,6 @@ const productSchema = new Schema({
},
maxBookableSinglePersQty: { // quantità massima Pre-ordinabile (singolarmente)
type: Number,
default: 0,
},
stockQty: { // in magazzino
type: Number,
@@ -141,58 +140,45 @@ const productSchema = new Schema({
},
stockBloccatiQty: { // Prenotati Bloccati
type: Number,
default: 0,
},
bookedQtyOrdered: { // Quantità Prenotate ordinate (in Lavorazione)
type: Number,
default: 0,
},
bookedQtyConfirmed: { // Quantità Prenotate Confermate Totali
type: Number,
default: 0,
},
// GAS:
qtyToReachForGas: { // Quantità minima da raggiungere per fare l'ordine GAS
type: Number,
default: 0,
},
maxbookableGASQty: { // Quantità massima (ancora disponibile) Ordine GAS prenotabile (Complessivamente tra tutti gli ordini)
type: Number,
default: 0,
},
bookedGASQtyOrdered: { // Quantità Ordine GAS Prenotate Totali
type: Number,
default: 0,
},
bookedGASQtyConfirmed: { // Quantità Ordine GAS Confermate Totali
type: Number,
default: 0,
},
bookableGASBloccatiQty: { // Quantità Prenotate Bloccate GAS
type: Number,
default: 0,
},
quantityLow: { //Soglia disponibilità bassa
type: Number,
default: 0,
},
visibilityProductOutOfStock: { // Visibilità prodotto "esaurito"
type: Boolean,
default: false,
},
canBeShipped: { // è spedibile
type: Boolean,
default: false,
},
canBeBuyOnline: { // è acquistabile online
type: Boolean,
default: false,
},
stars: {
type: Number,
default: 0,
},
dateAvailableFrom: {
type: Date
@@ -279,48 +265,24 @@ module.exports.executeQueryPickup = async function (idapp, params) {
// 🔹 Pattern per productInfo.name: tutte le parole devono essere presenti
const patternAllWords = words.map(w => `(?=.*\\b${escapeRegex(w)})`).join('') + '.*';
// 🔹 Condizioni per autori
let authorConditions = [];
// Se ci sono esattamente 2 parole (es. "antonio graziano")
if (words.length === 2) {
const [w1, w2] = words.map(escapeRegex);
authorConditions = [
{
'productInfo.authors': {
$elemMatch: {
name: { $regex: `^${w1}`, $options: 'i' },
surname: { $regex: `^${w2}`, $options: 'i' }
}
}
},
{
'productInfo.authors': {
$elemMatch: {
name: { $regex: `^${w2}`, $options: 'i' },
surname: { $regex: `^${w1}`, $options: 'i' }
}
}
}
];
}
// Se c'è solo una parola (es. "antonio")
if (words.length === 1) {
const word = escapeRegex(words[0]);
authorConditions = [
{
if (words.length > 0) {
authorConditions = words.map((word) => {
const regex = new RegExp(escapeRegex(word), 'i');
return {
'productInfo.authors': {
$elemMatch: {
$or: [
{ name: { $regex: `^${word}`, $options: 'i' } },
{ surname: { $regex: `^${word}`, $options: 'i' } }
{ name: regex },
{ surname: regex }
]
}
}
}
];
};
});
authorConditions = [{ $and: authorConditions }];
}
// 🔹 Filtro finale
@@ -780,6 +742,7 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
} catch (e) {
console.error('E', e);
return [];
}

View File

@@ -67,11 +67,9 @@ const productInfoSchema = new Schema({
},
unit: {
type: Number,
default: 0,
},
unit_lordo: {
type: Number,
default: 0,
},
sfuso: { // serve se moltiplicare le qta (es: 12 kg) oppure fare (2 x 20 ml)
type: Boolean
@@ -157,8 +155,9 @@ const productInfoSchema = new Schema({
fatLast3M: Number,
fatLast6M: Number,
fatLast1Y: Number,
fatLast2Y: Number,
vLast6M: Number,
vLastY: Number,
vLast1Y: Number,
vLast2Y: Number,
dataUltimoOrdine: Date,
rank3M: Number,
@@ -467,61 +466,16 @@ module.exports.updateProductInfoByStats = async function (idapp) {
console.log(mylog);
// Itera sui risultati e aggiorna productInfo
let countUpdate = 0;
for (const stat of statistics) {
const result = await ProductInfo.updateOne(
{
sku: stat.sku,
idapp
}, // Cerca il documento con lo stesso sku
{
$set: {
fatLast3M: stat.fatLast3M,
fatLast6M: stat.fatLast6M,
fatLast1Y: stat.fatLast1Y
}
},
{ upsert: false } // Non crea il documento se non esiste
);
if (result.modifiedCount > 0) {
countUpdate++;
}
}
mylog = `Aggiornati ${countUpdate} record di productInfo`;
mylogtot += mylog;
console.log(mylog);
// Ottieni le statistiche dalla query
const statisticsordini = await T_WEB_Ordini.getStatisticsFromOrders();
mylog2 = "Inizio Aggiornamento Statistiche Ordini ... \n";
mylogtot += mylog2;
console.log(mylog2);
// Itera sui risultati e aggiorna productInfo
countUpdate = 0;
for (const stat of statisticsordini) {
const result = await ProductInfo.updateOne(
{
sku: stat.sku,
idapp
}, // Cerca il documento con lo stesso sku
{
$set: {
totVen: stat.totVen,
vLast3M: stat.vLast3M,
vLast6M: stat.vLast6M,
vLastY: stat.vLastY,
vLast2Y: stat.vLast2Y,
}
},
{ upsert: false } // Non crea il documento se non esiste
);
if (result.modifiedCount > 0) {
countUpdate++;
}
}
countUpdate = await T_WEB_Ordini.updateStatisticsOrders('', idapp, true);
mylog2 = `Aggiornati ${countUpdate} record di productInfo`;
mylogtot += mylog2;

View File

@@ -45,6 +45,62 @@ module.exports.findAllIdApp = async function (idapp) {
return await Publisher.find(myfind).sort({ name: 1 }).lean();
};
module.exports.getEditoriWithTitleCount = async function (idapp) {
try {
const myquery = [
{ $match: { idapp } },
{
$lookup: {
from: 'productinfos', // Nome della tua collezione productInfo
localField: '_id',
foreignField: 'idPublisher',
as: 'products'
}
},
{
$addFields: {
myproducts: {
$filter: {
input: "$products",
as: "prod",
cond: {
$in: ["$$prod.idStatoProdotto", [1, 4, 34, 45, 46]]
}
}
}
}
}, {
$project: {
_id: 1,
name: 1,
quanti: { $size: '$myproducts' },
products: {
$map: {
input: "$myproducts",
as: "prod",
in: {
name: "$$prod.name"
}
}
}
}
},
{ $match: { quanti: { $gt: 0 } } }, // esclude i record con quanti = 0
{ $sort: { name: 1 } } // Ordina i risultati per nome
];
const result = await Publisher.aggregate(myquery);
return result;
} catch (error) {
console.error('Error retrieving idCollana with title count:', error);
throw error;
}
}
module.exports.createIndexes()
.then(() => { })
.catch((err) => { throw err; });

View File

@@ -1,5 +1,7 @@
const mongoose = require('mongoose');
const ProductInfo = require('../models/productInfo');
// Definizione dello schema
const articoliFatturatiSchema = new mongoose.Schema({
Codice: {
@@ -59,7 +61,7 @@ const articoliFatturatiSchema = new mongoose.Schema({
var articoliFatturati = module.exports = mongoose.model('T_WEB_ArticoliFatturati', articoliFatturatiSchema);
// Funzione per calcolare le statistiche
module.exports.getStatistics = async function () {
module.exports.updateStatisticsFatt = async function (CodArticolo, idapp, update) {
const currentDate = new Date();
// Calcola le date limite per i periodi di 3 mesi, 6 mesi e 1 anno
@@ -71,15 +73,30 @@ module.exports.getStatistics = async function () {
const oneYearAgo = new Date(currentDate);
oneYearAgo.setFullYear(currentDate.getFullYear() - 1);
const twoYearAgo = new Date(currentDate);
twoYearAgo.setFullYear(currentDate.getFullYear() - 2);
const fiveYearAgo = new Date(currentDate);
fiveYearAgo.setFullYear(currentDate.getFullYear() - 5);
try {
let myquery = [];
// Query di aggregazione per calcolare le statistiche
const myquery = [
myquery.push(
{
$match: {
DataOra: { $gte: oneYearAgo } // Filtra solo i record degli ultimi 12 mesi
DataOra: { $gte: fiveYearAgo } // Filtra solo i record degli ultimi 12 mesi
}
},
});
if (CodArticolo) {
myquery.push({
$match: { $expr: { $eq: ["$CodArticolo", CodArticolo] } }
})
}
myquery.push(
{
$group: {
_id: "$CodArticolo", // Raggruppa per CodArticolo
@@ -109,7 +126,25 @@ module.exports.getStatistics = async function () {
0 // Altrimenti, somma 0
]
}
}
},
fatLast2Y: {
$sum: {
$cond: [
{ $gte: ["$DataOra", twoYearAgo] }, // Condizione: DataOra >= 1 anno fa
{ $toInt: "$Qta" }, // Se vero, somma la quantità
0 // Altrimenti, somma 0
]
}
},
totFat: {
$sum: {
$cond: [
{ $gte: ["$DataOra", fiveYearAgo] }, //
{ $toInt: "$Qta" }, // Se vero, somma la quantità
0 // Altrimenti, somma 0
]
}
},
}
},
{
@@ -119,16 +154,45 @@ module.exports.getStatistics = async function () {
fatLast3M: 1,
fatLast6M: 1,
fatLast1Y: 1,
fatLast2Y: 1,
totFat: 1,
}
}
];
);
const statistics = await articoliFatturati.aggregate(myquery);
return statistics;
let countUpdate = 0;
if (update) {
for (const stat of statistics) {
const result = await ProductInfo.updateOne(
{
sku: stat.sku,
idapp
}, // Cerca il documento con lo stesso sku
{
$set: {
fatLast3M: stat.fatLast3M,
fatLast6M: stat.fatLast6M,
fatLast1Y: stat.fatLast1Y,
fatLast2Y: stat.fatLast2Y,
totFat: stat.totFat,
}
},
{ upsert: false } // Non crea il documento se non esiste
);
if (result.modifiedCount > 0) {
countUpdate++;
}
}
}
return countUpdate;
} catch (error) {
console.error("Errore durante il calcolo delle statistiche:", error);
throw error;
// throw error;
return 0;
}
}

View File

@@ -18,6 +18,8 @@ PrimaCopiaDaSpedire - int ()
const mongoose = require('mongoose');
const ProductInfo = require('../models/productInfo');
// Definizione dello schema
const ordiniSchema = new mongoose.Schema({
Codice: {
@@ -63,7 +65,7 @@ const ordiniSchema = new mongoose.Schema({
var T_WEB_Ordini = module.exports = mongoose.model('T_WEB_Ordini', ordiniSchema);
module.exports.getStatisticsFromOrders = async function () {
module.exports.updateStatisticsOrders = async function (CodArticoloGM, idapp, update) {
const currentDate = new Date();
// Calcola le date limite per i periodi di 3 mesi, 6 mesi e 1 anno
@@ -75,24 +77,31 @@ module.exports.getStatisticsFromOrders = async function () {
const oneYearAgo = new Date(currentDate);
oneYearAgo.setFullYear(currentDate.getFullYear() - 1);
const twoYearAgo = new Date(currentDate);
twoYearAgo.setFullYear(currentDate.getFullYear() - 2);
const allYear = new Date(currentDate);
allYear.setFullYear(currentDate.getFullYear() - 20);
const fiveYear = new Date(currentDate);
fiveYear.setFullYear(currentDate.getFullYear() - 5);
try {
let myquery = [];
// Query di aggregazione per calcolare le statistiche
const myquery = [
myquery.push(
{
$match: {
CodArticoloGM: CodArticoloGM,
},
});
myquery.push(
{
$group: {
_id: "$CodArticoloGM", // Raggruppa per CodArticolo
totVen: {
$sum: {
$cond: [
{ $gte: ["$DataOra", allYear] }, // Condizione: DataOra totale
{ $gte: ["$DataOra", fiveYear] }, // Condizione: DataOra totale
{ $toInt: "$Qta" }, // Se vero, somma la quantità
0 // Altrimenti, somma 0
]
@@ -147,14 +156,41 @@ module.exports.getStatisticsFromOrders = async function () {
vLast2Y: 1,
}
}
];
);
const statistics = await T_WEB_Ordini.aggregate(myquery);
return statistics;
let countUpdate = 0;
if (update) {
for (const stat of statistics) {
const result = await ProductInfo.updateOne(
{
sku: stat.sku,
idapp,
}, // Cerca il documento con lo stesso sku
{
$set: {
totVen: stat.totVen,
vLast3M: stat.vLast3M,
vLast6M: stat.vLast6M,
vLast1Y: stat.vLast1Y,
vLast2Y: stat.vLast2Y,
}
},
{ upsert: false } // Non crea il documento se non esiste
);
if (result.modifiedCount > 0) {
countUpdate++;
}
}
}
return countUpdate;
} catch (error) {
console.error("Errore durante il calcolo delle statistiche:", error);
throw error;
return 0;
}
}

View File

@@ -13,6 +13,9 @@ const shared_consts = require('../tools/shared_nodejs'); // Assicurati di avere
const { getTableContent } = require('../controllers/articleController');
const T_WEB_ArticoliFatturati = require('../models/t_web_articolifatturati');
const T_WEB_Ordini = require('../models/t_web_ordini');
class Macro {
constructor(idapp, options) {
this.idapp = idapp;
@@ -58,26 +61,15 @@ class Macro {
if (options.usaDBGMLocale) {
mylog += '*** usaDBGMLocale ***\n';
//miomatch2 = { IdStatoProdotto: { $in: [1, 3, 4, 6, 7, 8, 9, 20, 26, 33, 34, 45, 46, 47, 48] } };
//miomatch2 = { IdStatoProdotto: { $in: [1, 4, 34, 45, 46] } };
miomatch2 = {
$or: [
{ DescrizioneStatoProdotto: 'In commercio' },
{ DescrizioneStatoProdotto: 'Ristampa' },
{ DescrizioneStatoProdotto: 'Prossima uscita/pubblicazione' },
{ DescrizioneStatoProdotto: 'In promozione' },
{ DescrizioneStatoProdotto: 'In fase di valutazione' },
{ DescrizioneStatoProdotto: 'Titolo in esaurimento (in attesa Nuova Edizione)' },
{ DescrizioneStatoProdotto: 'Titolo in esaurimento' },
{ DescrizioneStatoProdotto: 'Titolo in esaurimento (in att N.E Ricopertinata)' },
{ DescrizioneStatoProdotto: 'Titolo in Esaurimento (disponibile N.E.)' },
{ DescrizioneStatoProdotto: 'In commercio (digitale)' },
{ DescrizioneStatoProdotto: 'In prevendita' },
{ DescrizioneStatoProdotto: 'Vendita sito' },
{ DescrizioneStatoProdotto: '2023 in commercio' },
{ DescrizioneStatoProdotto: 'Assoluto NO Reso' },
{ DescrizioneStatoProdotto: 'Titolo esaurito' },
{ DescrizioneStatoProdotto: 'Prossima uscita' },
]
};
@@ -439,6 +431,13 @@ class Macro {
for (const recproduct of recproducts) {
// if (!options.caricatutti) {
await this.elaboraProdotto(recproduct, opt);
const sku = recproduct.IdArticolo;
if (sku) {
await T_WEB_ArticoliFatturati.updateStatisticsFatt(sku.toString(), options.idapp, true);
await T_WEB_Ordini.updateStatisticsOrders(sku.toString(), options.idapp, true);
}
count++;
if (count % 50 === 0) {
@@ -776,7 +775,7 @@ class Macro {
if (productGM.DescrizioneTipologia === 'Usato')
vers = shared_consts.PRODUCTTYPE.USATO;
if (productGM.DescrizioneTipologia === 'Download')
vers = shared_consts.PRODUCTTYPE.DOWNLOAD;
else if (productGM.DescrizioneTipologia === 'DVD')
@@ -791,8 +790,8 @@ class Macro {
vers = shared_consts.PRODUCTTYPE.STREAMING;
else
vers = shared_consts.PRODUCTTYPE.NUOVO;
recproduct.Versione = vers;
recproduct.Versione = vers;
return recproduct
}

View File

@@ -883,7 +883,7 @@ router.post('/import', authenticate, async (req, res) => {
totFat: 0,
vLast3M: 0,
vLast6M: 0,
vLastY: 0,
vLast1Y: 0,
vLast2Y: 0,
rank3M: 0,
rank6M: 0,
@@ -929,7 +929,7 @@ router.post('/import', authenticate, async (req, res) => {
fatLast3M: product.fatLast3M || 0,
fatLast6M: product.fatLast6M || 0,
vLast6M: product.vLast6M || 0,
vLastY: product.vLastY || 0,
vLast1Y: product.vLast1Y || 0,
vLast2Y: product.vLast2Y || 0,
rank3M: product.rank3M || 0,
rank6M: product.rank6M || 0,

View File

@@ -2016,9 +2016,9 @@ async function load(req, res, version = '0') {
catprods_gas: version >= 91 ? Product.getArrCatProds(idapp, shared_consts.PROD.GAS) : Promise.resolve([]),
catAI: version >= 91 ? CatAI.findAllIdApp(idapp) : Promise.resolve([]),
authors: version >= 91 ? Author.findAllIdApp(idapp) : Promise.resolve([]),
publishers: version >= 91 ? Publisher.findAllIdApp(idapp) : Promise.resolve([]),
publishers: version >= 91 ? Publisher.getEditoriWithTitleCount(idapp) : Promise.resolve([]),
myschedas: version >= 91 ? MyElem.findallSchedeTemplate(idapp) : Promise.resolve([]),
collane: version >= 91 ? Collana.findAllIdApp(idapp) : Promise.resolve([]),
collane: version >= 91 ? Collana.getCollaneWithTitleCount(idapp) : Promise.resolve([]),
catalogs: version >= 91 ? Catalog.findAllIdApp(idapp) : Promise.resolve([]),
catprtotali: version >= 91 ? CatProd.getCatProdWithTitleCount(idapp) : Promise.resolve([]),
stati_prodotto: version >= 91 ? T_WEB_StatiProdotto.findAllIdApp() : Promise.resolve([]),