- newsletter: prende la lista utenti (flag news_on)

- Abilita a Tutti la Newsletter news_on
- isCommerciale
- JobsInProgress
- PCB: Corretto Totali che era a zero
This commit is contained in:
Surya Paolo
2025-05-06 18:19:09 +02:00
parent 6e8d1fcff1
commit b77a0579f1
30 changed files with 4669 additions and 727 deletions

View File

@@ -0,0 +1,128 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
const shared_consts = require('../tools/shared_nodejs');
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const JobsInProgressSchema = new Schema({
idapp: {
type: String,
},
descr: {
type: String,
},
nomeFunzioneDbOp: {
type: String,
},
status: {
type: Number,
},
terminatedWhy: {
type: Number,
},
comment: {
type: String,
},
date_created: {
type: Date,
default: Date.now
},
});
JobsInProgressSchema.statics.chechifExistJobWorking = async function (jobData, terminateiftoolong) {
// controlla se esiste un altro job, non ancora terminato !STATUS_JOB.FINISH
// se esiste già allora ritorna false
const existingJob = await this.findOne({ idapp: jobData.idapp, nomeFunzioneDbOp: jobData.nomeFunzioneDbOp, status: { $ne: shared_consts.STATUS_JOB.FINISH } });
if (existingJob) {
// se il Job trovato è passato troppo tempo (oltre 3 ore date_created), allora fai finta che abbia già terminato
// (in questo caso, non ritorna false, ma ritorna il job trovato, per permettere di gestire il caso in cui si vuole forzare il job a terminare)
if (Math.abs(Date.now() - existingJob.date_created.getTime()) > 180 * 60 * 1000) {
if (terminateiftoolong) {
existingJob.status = shared_consts.STATUS_JOB.FINISH;
existingJob.terminatedWhy = shared_consts.TERMINATED_WHY.TOOLONGTIME;
await existingJob.save();
return false;
}
} else {
return true; // E' in FUNZIONE il JOB
}
}
return false;
};
JobsInProgressSchema.statics.addNewJob = async function (jobData) {
if (!jobData || typeof jobData !== 'object') {
console.error('ERRORE: ❌ jobData deve essere un oggetto valido');
}
const esistegia = await this.chechifExistJobWorking(jobData, true);
if (esistegia) {
return null;
}
try {
const newJob = await this.create(jobData);
return newJob;
} catch (err) {
console.error('Errore nell\'aggiungere un nuovo record: ', err);
throw err;
}
};
JobsInProgressSchema.methods.terminateJob = async function (witherror) {
try {
this.status = shared_consts.STATUS_JOB.FINISH;
this.terminatedWhy = witherror ? shared_consts.TERMINATED_WHY.END_WITHERROR : shared_consts.TERMINATED_WHY.END_NORMALLY;
await this.save();
return true;
} catch (err) {
console.error('Errore durante la terminazione del job: ', err);
return false;
}
};
JobsInProgressSchema.statics.getFieldsForSearch = function () {
return [{ field: 'descr', type: tools.FieldType.string }]
};
JobsInProgressSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
JobsInProgressSchema.statics.findAllIdApp = async function (idapp) {
const JobsInProgress = this;
try {
return await JobsInProgress.find({ idapp }).then((arrrec) => {
return arrrec;
});
} catch (err) {
console.error('Errore: ', err);
}
};
const JobsInProgress = mongoose.model('JobsInProgress', JobsInProgressSchema);
JobsInProgress.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { JobsInProgress };

View File

@@ -26,16 +26,17 @@ const CatalogSchema = new Schema({
},
title: {
type: String,
index: true,
},
foto_collana: IImg,
idCollane: [{
type: String,
}],
idTipoFormato: [{
type: Number,
}],
argomenti: [{
type: String,
}],
@@ -43,9 +44,9 @@ const CatalogSchema = new Schema({
type: Number,
default: 0,
},
editore: [{ type: String }],
descr_introduttiva: {
type: String,
},
@@ -93,6 +94,7 @@ const CatalogSchema = new Schema({
type: Schema.Types.ObjectId,
ref: 'Product',
}],
isCatalogoGenerale: Boolean,
});
/*
@@ -143,89 +145,102 @@ CatalogSchema.statics.executeQueryTable = function (idapp, params, user) {
CatalogSchema.statics.findAllIdApp = async function (idapp) {
const Catalog = this;
let arrrec = await Catalog.find({ idapp })
.sort({ title: 1 }) // Ordina i risultati per titolo
/*.populate({
path: "idCollane", // Popola il campo idCollane
model: "Collana" // Specifica il modello della collezione Collana
})*/
.populate({
path: "lista_prodotti", // Popola il campo lista_prodotti
populate: {
path: "idProductInfo",
model: "ProductInfo",
populate: [
{
path: "idCatProds",
model: "CatProd"
},
{
path: "idSubCatProds",
model: "SubCatProd"
},
{
path: "idAuthors",
model: "Author"
}
],
},
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProducer",
model: "Producer"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProvider",
model: "Provider"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idStorehouses",
model: "Storehouse"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idScontisticas",
model: "Scontistica"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idGasordine",
model: "Gasordine"
}
})
;
try {
let arrrec = await Catalog.find({ idapp })
.sort({ title: 1 }) // Ordina i risultati per titolo
/*.populate({
path: "idCollane", // Popola il campo idCollane
model: "Collana" // Specifica il modello della collezione Collana
})*/
.populate({
path: "lista_prodotti", // Popola il campo lista_prodotti
populate: {
path: "idProductInfo",
model: "ProductInfo",
populate: [
{
path: "idCatProds",
model: "CatProd"
},
{
path: "idSubCatProds",
model: "SubCatProd"
},
{
path: "idAuthors",
model: "Author"
}
],
},
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProducer",
model: "Producer"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idProvider",
model: "Provider"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idStorehouses",
model: "Storehouse"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idScontisticas",
model: "Scontistica"
}
})
.populate({
path: "lista_prodotti",
populate: {
path: "idGasordine",
model: "Gasordine"
}
})
;
const transformedArrRec = arrrec.map(catalog => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
...product.toObject(),
productInfo: {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo
catprods: product.idProductInfo.idCatProds, // Rinomina idCatProds in catprods
subcatprods: product.idProductInfo.idSubCatProds,
collana: product.idProductInfo.idCollana,
authors: product.idProductInfo.idAuthors,
},
producer: product.idProducer,
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
})),
}));
// controlla prima se nella lista ci sono dei product che non esistono piu allora li devi rimuovere !
for (const catalog of arrrec) {
const originalLength = catalog.lista_prodotti.length;
catalog.lista_prodotti = catalog.lista_prodotti.filter(product => product.idProductInfo);
if (catalog.lista_prodotti.length !== originalLength) {
await catalog.save();
}
}
return transformedArrRec;
const transformedArrRec = arrrec.map(catalog => ({
...catalog.toObject(), // Converte il documento Mongoose in un oggetto JavaScript puro
lista_prodotti: catalog.lista_prodotti.map(product => ({
...product.toObject(),
productInfo: {
...product.idProductInfo.toObject(), // Copia tutti i campi di idProductInfo
catprods: product.idProductInfo.idCatProds, // Rinomina idCatProds in catprods
subcatprods: product.idProductInfo.idSubCatProds,
collana: product.idProductInfo.idCollana,
authors: product.idProductInfo.idAuthors,
},
producer: product.idProducer,
storehouse: product.idStorehouses,
scontisticas: product.idScontisticas,
gasordine: product.idGasordine,
})),
}));
return transformedArrRec;
} catch (err) {
console.error('Errore: ', err);
}
};
const Catalog = mongoose.model('Catalog', CatalogSchema);

View File

@@ -21,6 +21,7 @@ const CatProdSchema = new Schema({
},
name: {
type: String,
index: 1,
},
descr_estesa: {
type: String,
@@ -100,7 +101,7 @@ CatProdSchema.statics.updateCatDeleteEmpty = async function (idapp) {
};
CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) {
CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp, updatedata) {
try {
const myquery = [
@@ -151,11 +152,13 @@ CatProdSchema.statics.getCatProdWithTitleCount = async function (idapp) {
const result = await CatProd.aggregate(myquery);
for (const record of result) {
await CatProd.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
if (updatedata) {
for (const record of result) {
await CatProd.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
}
}
return result;

View File

@@ -20,6 +20,7 @@ const CollanaSchema = new Schema({
},
title: {
type: String,
index: true,
},
dataOra: {
type: Date,
@@ -55,7 +56,7 @@ module.exports.findAllIdApp = async function (idapp) {
return await Collana.find(myfind).sort({title: 1}).lean();
};
module.exports.getCollaneWithTitleCount = async function (idapp) {
module.exports.getCollaneWithTitleCount = async function (idapp, updatedata) {
try {
const myquery = [
@@ -104,11 +105,13 @@ module.exports.getCollaneWithTitleCount = async function (idapp) {
const result = await Collana.aggregate(myquery);
for (const record of result) {
await Collana.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
if (updatedata) {
for (const record of result) {
await Collana.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
}
}
return result;

77
src/server/models/cron.js Executable file
View File

@@ -0,0 +1,77 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const CronSchema = new Schema({
idapp: {
type: String,
},
active: {
type: Boolean,
default: false,
},
descr: {
type: String,
},
nomeFunzioneDbOp: {
type: String,
},
startTime: { // Orario iniziale (es. "08:30")
type: String,
default: "00:00"
},
everyXHours: { // Esegui ogni X ore
type: Number,
default: 24
},
date_created: {
type: Date,
default: Date.now
},
date_updated: {
type: Date,
},
});
CronSchema.statics.getFieldsForSearch = function () {
return [{ field: 'descr', type: tools.FieldType.string }]
};
CronSchema.statics.executeQueryTable = function (idapp, params, user) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params, user);
};
CronSchema.statics.findAllIdApp = async function (idapp) {
const Cron = this;
try {
return await Cron.find({ idapp }).then((arrrec) => {
return arrrec;
});
} catch (err) {
console.error('Errore: ', err);
}
};
const Cron = mongoose.model('Cron', CronSchema);
Cron.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { Cron };

View File

@@ -0,0 +1,59 @@
const mongoose = require('mongoose').set('debug', false)
const Schema = mongoose.Schema;
const tools = require('../tools/general');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
const DestNewsletterSchema = new Schema({
idapp: {
type: String,
},
descr: {
type: String,
},
tipodest_id: {
type: Number,
},
});
DestNewsletterSchema.statics.getFieldsForSearch = function () {
return []
};
DestNewsletterSchema.statics.executeQueryTable = function (idapp, params) {
params.fieldsearch = this.getFieldsForSearch();
return tools.executeQueryTable(this, idapp, params);
};
DestNewsletterSchema.statics.DuplicateAllRecords = async function (idapporig, idappdest) {
return await tools.DuplicateAllRecords(this, idapporig, idappdest);
};
DestNewsletterSchema.statics.findAllIdApp = async function (idapp) {
const DestNewsletter = this;
const myfind = { idapp };
return await DestNewsletter.find(myfind).lean();
};
const DestNewsletter = mongoose.model('DestNewsletter', DestNewsletterSchema);
DestNewsletter.createIndexes()
.then(() => { })
.catch((err) => { throw err; });
module.exports = { DestNewsletter };

View File

@@ -39,6 +39,41 @@ MailingListSchema.statics.findAllIdAppSubscribed = function (idapp) {
return tools.findAllQueryIdApp(User, myfind);
};
MailingListSchema.statics.findAllIdAppDiarioSubscr = function (idapp) {
const myfind = {
idapp,
diario_on: true,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
$or: [
{ email_errata: { $exists: false } },
{ email_errata: { $exists: true, $ne: true } }],
};
// Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit.
return tools.findAllQueryIdApp(User, myfind);
};
MailingListSchema.statics.findAllIdAppDiarioSubscr = function (idapp) {
const myfind = {
idapp,
test: true,
$or: [
{ deleted: { $exists: false } },
{ deleted: { $exists: true, $eq: false } }],
$or: [
{ email_errata: { $exists: false } },
{ email_errata: { $exists: true, $ne: true } }],
};
// Extract only the Teacher where in the users table the field permissions is set 'Teacher' bit.
return tools.findAllQueryIdApp(User, myfind);
};
MailingListSchema.statics.getnumSent = async function (idapp, idUser) {
const myfind = { idapp, news_on: true, lastid_newstosent: idUser };

View File

@@ -22,6 +22,9 @@ const NewstosentSchema = new Schema({
templemail_str: {
type: String,
},
destnewsletter_str: {
type: String,
},
activate: {
type: Boolean,
default: false
@@ -121,7 +124,10 @@ NewstosentSchema.statics.findNewsletterPending_To_Send = function (idapp) {
starting_job: true,
finish_job: false,
processing_job: false,
lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 15) },
$or: [
{ lastemailsent_Job: { $gte: tools.IncDateNow(-1000 * 60 * 60 * 15) } },
{ lastemailsent_Job: null }
],
idapp
}).lean();
};

View File

@@ -22,9 +22,9 @@ const orderSchema = new Schema({
},
userId: { type: Schema.Types.ObjectId, ref: 'User' },
status: {
type: Number,
type: Number, index: true
},
idProduct: { type: Schema.Types.ObjectId, ref: 'Product' },
idProduct: { type: Schema.Types.ObjectId, ref: 'Product', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
idStorehouse: { type: Schema.Types.ObjectId, ref: 'StoreHouse' },
idScontisticas: [{ type: Schema.Types.ObjectId, ref: 'Scontistica' }],
@@ -125,7 +125,8 @@ const orderSchema = new Schema({
type: String
},
modify_at: {
type: Date
type: Date,
index: true
},
});

View File

@@ -36,16 +36,16 @@ const productSchema = new Schema({
isbn: {
type: String,
},
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo' },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer' },
idProductInfo: { type: Schema.Types.ObjectId, ref: 'ProductInfo', index: true },
idProducer: { type: Schema.Types.ObjectId, ref: 'Producer', index: true },
idStorehouses: [
{ type: Schema.Types.ObjectId, ref: 'Storehouse' }
{ type: Schema.Types.ObjectId, ref: 'Storehouse', index: true }
],
idGasordine: { type: Schema.Types.ObjectId, ref: 'Gasordine' },
idGasordine: { type: Schema.Types.ObjectId, ref: 'Gasordine', index: true },
idScontisticas: [
{ type: Schema.Types.ObjectId, ref: 'Scontistica' }
{ type: Schema.Types.ObjectId, ref: 'Scontistica', index: true }
],
idProvider: { type: Schema.Types.ObjectId, ref: 'Provider' },
idProvider: { type: Schema.Types.ObjectId, ref: 'Provider', index: true },
prezzo_ivato: { // Con IVA
type: Number
},
@@ -137,6 +137,7 @@ const productSchema = new Schema({
stockQty: { // in magazzino
type: Number,
default: 0,
index: true,
},
stockBloccatiQty: { // Prenotati Bloccati
type: Number,
@@ -220,7 +221,7 @@ const productSchema = new Schema({
},
validaprod: {
esito: {
type: Number,
type: Number,
},
data: {
type: Date,
@@ -468,176 +469,33 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
// return await Product.find(myfind);
query.push(
// PRIMO FILTRO: riduce subito il numero di documenti
{ $match: myfind },
// UNICO LOOKUP ORDERS CON FACET PER RIDURRE I DOPPIONI
{
$lookup: {
from: 'producers',
localField: 'idProducer',
foreignField: '_id',
as: 'producer'
}
},
{
$unwind: {
path: '$producer',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'productinfos',
localField: 'idProductInfo',
foreignField: '_id',
as: 'productInfo'
}
},
{
$unwind: {
path: '$productInfo',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'gasordines',
localField: 'idGasordine',
foreignField: '_id',
as: 'gasordine'
}
},
{
$unwind: {
path: '$gasordine',
preserveNullAndEmptyArrays: true,
},
},
{
$match: {
$or: [
{ 'gasordine.active': true }, // Include documents where gasordines.active is true
{ 'gasordine': { $exists: false } } // Include documents where gasordines array doesn't exist
]
}
},
{
$group: {
_id: '$_id',
gasordine: { $first: '$gasordine' },
originalFields: { $first: '$$ROOT' } // Preserve all existing fields
}
},
{
$replaceRoot: {
newRoot: {
$mergeObjects: ['$originalFields', { gasordine: '$gasordine' }]
}
}
},
{
$lookup: {
from: 'providers',
localField: 'idProvider',
foreignField: '_id',
as: 'provider'
}
},
{
$unwind: {
path: '$provider',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'authors',
localField: 'productInfo.idAuthors',
foreignField: '_id',
as: 'productInfo.authors'
}
},
{
$lookup: {
from: 'publishers',
localField: 'productInfo.idPublisher',
foreignField: '_id',
as: 'productInfo.publisher'
}
},
{
$unwind: {
path: '$productInfo.publisher',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'collanas',
localField: 'productInfo.idCollana',
foreignField: '_id',
as: 'productInfo.collana'
}
},
{
$unwind: {
path: '$productInfo.collana',
preserveNullAndEmptyArrays: true,
},
},
{
$lookup: {
from: 'catprods',
localField: 'productInfo.idCatProds',
foreignField: '_id',
as: 'productInfo.catprods'
}
},
{
$lookup: {
from: 'subcatprods',
localField: 'productInfo.idSubCatProds',
foreignField: '_id',
as: 'productInfo.subcatprods'
}
},
{
$lookup: {
from: 'scontisticas',
localField: 'idScontisticas',
foreignField: '_id',
as: 'scontisticas'
}
},
{
$lookup: {
from: 'storehouses',
localField: 'idStorehouses',
foreignField: '_id',
as: 'storehouses'
}
},
{
$lookup: {
from: 'orders',
let: { productId: '$_id' },
from: "orders",
let: { productId: "$_id" },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$idProduct', '$$productId'] },
{ $eq: ["$idProduct", "$$productId"] },
{
$or: [
{ $eq: ["$status", shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$eq: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT]
},
{
$and: [{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
]
}]
$and: [
{ $lt: ["$status", shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
"$modify_at",
{ $subtract: [new Date(), 60 * 60 * 1000] }
]
}
]
}
]
}
@@ -648,102 +506,162 @@ module.exports.findAllIdApp = async function (idapp, code, id, all) {
{
$group: {
_id: null,
totalQty: { $sum: '$quantity' },
totalQty: { $sum: "$quantity" },
totalQtyPreordered: { $sum: "$quantitypreordered" }
}
}
],
as: 'productOrders'
}
},
{
$lookup: {
from: 'orders',
let: { productId: '$_id' },
pipeline: [
{
$match: {
$expr: {
$and: [
{ $eq: ['$idProduct', '$$productId'] },
{
$or: [
{
$eq: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT]
},
{
$and: [{ $lt: ['$status', shared_consts.OrderStatus.CHECKOUT_SENT] },
{
$gt: [
'$modify_at',
{ $subtract: [new Date(), 60 * 60 * 1000] } // 1 hour in milliseconds 60 * 60
]
}]
}
]
}
]
}
}
},
{
$group: {
_id: null,
totalQtyPreordered: { $sum: '$quantitypreordered' }
}
}
],
as: 'productPreOrders'
as: "orderSummary"
}
},
// ESTRAGGO LE QUANTITÀ IN CAMPI AGGIUNTIVI
{
$addFields: {
QuantitaOrdinateInAttesa: {
$ifNull: [
{
$cond: {
if: { $isArray: '$productOrders' },
then: { $arrayElemAt: ['$productOrders.totalQty', 0] },
else: 0
}
},
0
]
$ifNull: [{ $arrayElemAt: ["$orderSummary.totalQty", 0] }, 0]
},
QuantitaPrenotateInAttesa: {
$ifNull: [
{
$cond: {
if: { $isArray: '$productPreOrders' },
then: { $arrayElemAt: ['$productPreOrders.totalQtyPreordered', 0] },
else: 0
}
},
0
]
},
},
},
{
$addFields: {
quantityAvailable: {
$subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"],
},
bookableAvailableQty: {
$subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"],
$ifNull: [{ $arrayElemAt: ["$orderSummary.totalQtyPreordered", 0] }, 0]
}
}
},
// CALCOLO DELLE DISPONIBILITÀ
{
$unset: 'productOrders'
},
{
$unset: 'productPreOrders'
},
{
$sort: {
'productInfo.name': 1 // 1 for ascending order, -1 for descending order
$addFields: {
quantityAvailable: {
$subtract: ["$stockQty", "$QuantitaOrdinateInAttesa"]
},
bookableAvailableQty: {
$subtract: ["$maxbookableGASQty", "$QuantitaPrenotateInAttesa"]
}
}
},
// ELIMINO IL RISULTATO TEMPORANEO
{ $unset: "orderSummary" },
// LOOKUP MULTIPLI MA ORGANIZZATI
{
$lookup: {
from: "producers",
localField: "idProducer",
foreignField: "_id",
as: "producer"
}
},
{ $unwind: { path: "$producer", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "productinfos",
localField: "idProductInfo",
foreignField: "_id",
as: "productInfo"
}
},
{ $unwind: { path: "$productInfo", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "gasordines",
localField: "idGasordine",
foreignField: "_id",
as: "gasordine"
}
},
{ $unwind: { path: "$gasordine", preserveNullAndEmptyArrays: true } },
// FILTRO DOPO LOOKUP SU GASORDINE
{
$match: {
$or: [
{ "gasordine.active": true },
{ gasordine: { $exists: false } }
]
}
},
// LOOKUP SU AUTHORS
{
$lookup: {
from: "authors",
localField: "productInfo.idAuthors",
foreignField: "_id",
as: "productInfo.authors"
}
},
// LOOKUP PUBBLICATORI, COLLANE, CATEGORIE, ECC.
{
$lookup: {
from: "publishers",
localField: "productInfo.idPublisher",
foreignField: "_id",
as: "productInfo.publisher"
}
},
{ $unwind: { path: "$productInfo.publisher", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "collanas",
localField: "productInfo.idCollana",
foreignField: "_id",
as: "productInfo.collana"
}
},
{ $unwind: { path: "$productInfo.collana", preserveNullAndEmptyArrays: true } },
{
$lookup: {
from: "catprods",
localField: "productInfo.idCatProds",
foreignField: "_id",
as: "productInfo.catprods"
}
},
{
$lookup: {
from: "subcatprods",
localField: "productInfo.idSubCatProds",
foreignField: "_id",
as: "productInfo.subcatprods"
}
},
{
$lookup: {
from: "scontisticas",
localField: "idScontisticas",
foreignField: "_id",
as: "scontisticas"
}
},
{
$lookup: {
from: "storehouses",
localField: "idStorehouses",
foreignField: "_id",
as: "storehouses"
}
},
{
$lookup: {
from: "providers",
localField: "idProvider",
foreignField: "_id",
as: "provider"
}
},
{ $unwind: { path: "$provider", preserveNullAndEmptyArrays: true } },
// ORDINAMENTO FINALE
{
$sort: {
"productInfo.name": 1
}
}
);
// console.log('query=', query);

View File

@@ -41,6 +41,7 @@ const productInfoSchema = new Schema({
},
name: {
type: String,
index: true,
},
description: {
type: String,
@@ -48,10 +49,10 @@ const productInfoSchema = new Schema({
short_descr: {
type: String,
},
idCatProds: [{ type: Schema.Types.ObjectId, ref: 'CatProd' }],
idCatProds: [{ type: Schema.Types.ObjectId, ref: 'CatProd', index: true }],
idSubCatProds: [{ type: Schema.Types.ObjectId, ref: 'SubCatProd' }],
idStatoProdotto: {
type: Number
type: Number, index: true
},
color: {
type: String
@@ -86,6 +87,9 @@ const productInfoSchema = new Schema({
imagefile: {
type: String,
},
image_not_found: {
type: Boolean,
},
vers_img: {
type: Number,
},
@@ -122,9 +126,9 @@ const productInfoSchema = new Schema({
note: {
type: String,
},
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author' }],
idCollana: { type: Schema.Types.ObjectId, ref: 'Collana' },
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher' },
idAuthors: [{ type: Schema.Types.ObjectId, ref: 'Author', index: true }],
idCollana: { type: Schema.Types.ObjectId, ref: 'Collana', index: true },
idPublisher: { type: Schema.Types.ObjectId, ref: 'Publisher', index: true },
collezione: {
type: String,
},
@@ -133,6 +137,7 @@ const productInfoSchema = new Schema({
},
date_pub: {
type: Date,
index: 1,
},
date_pub_ts: {
type: Number,
@@ -144,7 +149,7 @@ const productInfoSchema = new Schema({
date_updated: {
type: Date,
},
date_updated_fromGM: {
type: Date,
},
@@ -156,8 +161,13 @@ const productInfoSchema = new Schema({
fatLast6M: Number,
fatLast1Y: Number,
fatLast2Y: Number,
vLast6M: Number,
vLast1Y: Number,
vLast6M: {
type: Number,
index: true,
},
vLast1Y: {
type: Number, index: true
},
vLast2Y: Number,
dataUltimoOrdine: Date,
rank3M: Number,
@@ -492,6 +502,60 @@ module.exports.updateProductInfoByStats = async function (idapp) {
return mylogtot;
}
// crea setImgNotFound
module.exports.setImgNotFound = async function (id) {
// set sul record id il flag image_not_found
try {
const ProductInfo = this;
await ProductInfo.updateOne(
{ _id: id },
{ $set: { image_not_found: true } }
);
console.log(`Flag image_not_found set for record with id: ${id}`);
} catch (error) {
console.error(`Error setting image_not_found flag for id ${id}:`, error);
}
}
// crea una funzione che mi rimuove il record "product" che utilizza productInfo, nel caso in cui date_updated_fromGM non esista
module.exports.removeProductInfoWithoutDateUpdatedFromGM = async function (idapp) {
const ProductInfo = this;
const globalTables = require('../tools/globalTables');
const Product = globalTables.getTableByTableName('Product');
let mylog;
try {
const arrproductInfo = await ProductInfo.find({ idapp, date_updated_fromGM: { $exists: false } });
if (arrproductInfo.length > 0) {
mylog = `Rimuovo ${arrproductInfo.length} productInfo senza date_updated_fromGM !!`
console.log(mylog);
for (const productinfo of arrproductInfo) {
// cerca nella tabella Product se esiste idProductInfo = _id e cancella tutti i record che hanno questa corrispondenza
if (Product) {
await Product.deleteMany({ idProductInfo: productinfo._id });
}
// Ora rimuovi anche questo productInfo
await ProductInfo.deleteOne({ _id: productinfo._id });
}
}
return mylog;
} catch (error) {
mylog += 'Error removing productInfo without date_updated_fromGM:' + error;
console.error(mylog);
}
return mylog;
};
module.exports.createIndexes()
.then(() => { })
.catch((err) => { throw err; });

View File

@@ -48,7 +48,7 @@ module.exports.findAllIdApp = async function (idapp) {
return await Publisher.find(myfind).sort({ name: 1 }).lean();
};
module.exports.getEditoriWithTitleCount = async function (idapp) {
module.exports.getEditoriWithTitleCount = async function (idapp, updatedata) {
try {
const myquery = [
@@ -95,11 +95,13 @@ module.exports.getEditoriWithTitleCount = async function (idapp) {
const result = await Publisher.aggregate(myquery);
for (const record of result) {
await Publisher.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
if (updatedata) {
for (const record of result) {
await Publisher.updateOne(
{ _id: record._id },
{ $set: { quanti: record.quanti } }
);
}
}
return result;

View File

@@ -25,6 +25,15 @@ const TemplEmailSchema = new Schema({
content: {
type: String,
},
disclaimer: {
type: String,
},
piedipagina: {
type: String,
},
firma: {
type: String,
},
img: {
type: String,
},

View File

@@ -177,6 +177,12 @@ const UserSchema = new mongoose.Schema({
news_on: {
type: Boolean,
},
diario_on: {
type: Boolean,
},
test: {
type: Boolean,
},
email_errata: {
type: Boolean,
},
@@ -640,7 +646,7 @@ UserSchema.statics.canHavePower = function (perm) {
try {
let consentito = false;
if (User.isAdmin(perm) || User.isManager(perm) ||
User.isEditor(perm) || User.isFacilitatore(perm)) {
User.isEditor(perm) || User.isCommerciale(perm) || User.isFacilitatore(perm)) {
consentito = true;
}
@@ -696,6 +702,14 @@ UserSchema.statics.isEditor = function (perm) {
return false;
}
};
UserSchema.statics.isCommerciale = function (perm) {
try {
return ((perm & shared_consts.Permissions.Commerciale) ===
shared_consts.Permissions.Commerciale);
} catch (e) {
return false;
}
};
UserSchema.statics.isGrafico = function (perm) {
try {
return ((perm & shared_consts.Permissions.Grafico) ===
@@ -759,7 +773,7 @@ UserSchema.statics.findByToken = async function (token, typeaccess, con_auth, wi
if (!token) {
console.warn('TOKEN VUOTO ! ');
return { user, code };
}
}
try {
@@ -822,7 +836,7 @@ UserSchema.statics.findByToken = async function (token, typeaccess, con_auth, wi
const end_find = process.hrtime.bigint();
// console.log(` User.findOne LEAN impiega ${Math.round(Number(end_find - start_find) / 1e6) / 1000} secondi.`);
}
if (user) {
const checkExpiry = tools.getEnableTokenExpiredByIdApp(user.idapp);
@@ -1350,6 +1364,16 @@ UserSchema.statics.setaportador_solidario = async function (
return !!myrec;
};
UserSchema.statics.setNewsletterToAll = async function (
idapp) {
const User = this;
return await User.updateMany({
idapp,
$or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }],
}, { $set: { 'news_on': true } },
{ new: false });
};
UserSchema.statics.setNewsletter = async function (
idapp, username, newsletter_on) {
const User = this;