- aggiornamenti guida RIS, FAQ
- Editor HTML aggiunto CSS e Script - Statistiche - CRISBalanceBar - Inizio Sync... (ma disattivato)
This commit is contained in:
@@ -40,7 +40,8 @@ mongoose.plugin((schema) => {
|
|||||||
|
|
||||||
mongoose.set('debug', false);
|
mongoose.set('debug', false);
|
||||||
|
|
||||||
const UserSchema = new mongoose.Schema({
|
const UserSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
userId: {
|
userId: {
|
||||||
type: String,
|
type: String,
|
||||||
},
|
},
|
||||||
@@ -231,6 +232,7 @@ const UserSchema = new mongoose.Schema({
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
deletedAt: Date,
|
||||||
sospeso: {
|
sospeso: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
},
|
},
|
||||||
@@ -580,7 +582,12 @@ const UserSchema = new mongoose.Schema({
|
|||||||
version: { type: Number },
|
version: { type: Number },
|
||||||
insert_circuito_ita: { type: Boolean },
|
insert_circuito_ita: { type: Boolean },
|
||||||
},
|
},
|
||||||
});
|
updatedAt: { type: Date, default: Date.now },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
timestamps: true, // Mongoose aggiorna automaticamente updatedAt
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
UserSchema.methods.toJSON = function () {
|
UserSchema.methods.toJSON = function () {
|
||||||
const user = this;
|
const user = this;
|
||||||
@@ -6960,7 +6967,6 @@ UserSchema.statics.isEnableToReceiveEmailByUsernameECmd = async function (idapp,
|
|||||||
let ricevo = true;
|
let ricevo = true;
|
||||||
if (cmd === shared_consts.CIRCUITCMD.SETFIDO) {
|
if (cmd === shared_consts.CIRCUITCMD.SETFIDO) {
|
||||||
// Controllo se l'utente ha scelto di ricevere l'email
|
// Controllo se l'utente ha scelto di ricevere l'email
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ricevo;
|
return ricevo;
|
||||||
@@ -6983,6 +6989,28 @@ UserSchema.statics.getTokenByUsernameAndCircuitName = async function (idapp, use
|
|||||||
return user?.profile?.mycircuits?.[0]?.token || null;
|
return user?.profile?.mycircuits?.[0]?.token || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
UserSchema.statics.softDelete = async function(id) {
|
||||||
|
return this.findByIdAndUpdate(
|
||||||
|
id,
|
||||||
|
{
|
||||||
|
deleted: true,
|
||||||
|
deletedAt: new Date()
|
||||||
|
},
|
||||||
|
{ new: true }
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
UserSchema.statics.getUsersList = function(idapp) {
|
||||||
|
return this.find({
|
||||||
|
idapp: idapp,
|
||||||
|
$or: [
|
||||||
|
{ deleted: { $exists: false } },
|
||||||
|
{ deleted: false }
|
||||||
|
]
|
||||||
|
}).lean();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const User = mongoose.model('User', UserSchema);
|
const User = mongoose.model('User', UserSchema);
|
||||||
|
|
||||||
class Hero {
|
class Hero {
|
||||||
@@ -7039,7 +7067,7 @@ const FuncUsers = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
UserSchema.index({ 'tokens.token': 1, 'tokens.access': 1 });
|
UserSchema.index({ 'tokens.token': 1, 'tokens.access': 1, idapp: 1, deleted: 1, updatedAt: 1 });
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
User,
|
User,
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
list: [
|
list: [
|
||||||
{_id: 1, descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'blue-7'},
|
{_id: 1, descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'blue-7'},
|
||||||
{_id: 2, descr: 'Arredamento', icon: 'fas fa-chair', color: 'green-7'},
|
{_id: 2, descr: 'Arredamento', icon: 'fas fa-couch', color: 'brown-7'},
|
||||||
{_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'orange-7'},
|
{_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'grey-9'},
|
||||||
{_id: 4, descr: 'Artigianato', icon: 'fas fa-screwdriver', color: 'red-7'},
|
{_id: 4, descr: 'Artigianato', icon: 'fas fa-gem', color: 'amber-7'},
|
||||||
{_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'purple-7'},
|
{_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'pink-7'},
|
||||||
{_id: 6, descr: 'Bimbi', icon: 'fas fa-child', color: 'cyan-7'},
|
{_id: 6, descr: 'Bimbi', icon: 'fas fa-baby', color: 'cyan-7'},
|
||||||
{_id: 7, descr: 'Cibo'},
|
{_id: 7, descr: 'Cibo', icon: 'fas fa-utensils', color: 'orange-7'},
|
||||||
{_id: 8, descr: 'Collezionismo e Antiquariato'},
|
{_id: 8, descr: 'Collezionismo e Antiquariato', icon: 'fas fa-coins', color: 'brown-9'},
|
||||||
{_id: 9, descr: 'Elettronica di Consumo'},
|
{_id: 9, descr: 'Elettronica', icon: 'fas fa-laptop', color: 'blue-grey-8'},
|
||||||
{_id: 10, descr: 'Giochi', icon: 'fas fa-gamepad', color: 'purple-7'},
|
{_id: 10, descr: 'Giochi', icon: 'fas fa-gamepad', color: 'purple-7'},
|
||||||
{_id: 11, descr: 'Hobby', icon: 'fas fa-guitar', color: 'cyan-7'},
|
{_id: 11, descr: 'Hobby e Fai da Te', icon: 'fas fa-palette', color: 'deep-orange-6'},
|
||||||
{_id: 12, descr: 'Libri', icon: 'fas fa-book', color: 'indigo-7'},
|
{_id: 12, descr: 'Libri', icon: 'fas fa-book-open', color: 'indigo-7'},
|
||||||
{_id: 13, descr: 'Musica e Film', icon: 'fas fa-music', color: 'brown-7'},
|
{_id: 13, descr: 'Musica e Film', icon: 'fas fa-film', color: 'deep-purple-7'},
|
||||||
{_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-graduation-cap', color: 'pink-7'},
|
{_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-pen', color: 'blue-8'},
|
||||||
{_id: 15, descr: 'Sport', icon: 'fas fa-futbol', color: 'orange-7'},
|
{_id: 15, descr: 'Sport', icon: 'fas fa-bicycle', color: 'green-8'},
|
||||||
{_id: 16, descr: 'Un po\' di Tutto', icon: 'fas fa-globe-europe', color: 'red-7'},
|
{_id: 16, descr: 'Varie', icon: 'fas fa-box', color: 'grey-7'},
|
||||||
{_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'blue-7'},
|
{_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'grey-8'},
|
||||||
{_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'green-7'},
|
{_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'brown-6'},
|
||||||
{_id: 19, descr: 'Arte / Decorazioni', icon: 'fas fa-palette', color: 'purple-7'},
|
{_id: 19, descr: 'Arte e Decorazioni', icon: 'fas fa-palette', color: 'purple-6'},
|
||||||
{_id: 20, descr: 'Agricoltura', icon: 'fas fa-seedling', color: 'green-7'},
|
{_id: 20, descr: 'Agricoltura', icon: 'fas fa-seedling', color: 'green-7'},
|
||||||
|
{_id: 21, descr: 'Elettrodomestici', icon: 'fas fa-plug', color: 'blue-grey-7'},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
29
src/routes/sync.js
Normal file
29
src/routes/sync.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// server/routes/sync.js
|
||||||
|
const express = require('express');
|
||||||
|
const router = express.Router();
|
||||||
|
const SyncManager = require('../services/SyncManager');
|
||||||
|
const { authenticate_noerror_WithUserLean } = require('../middleware/authenticate');
|
||||||
|
|
||||||
|
router.post('/sync/:idapp', authenticate_noerror_WithUserLean, async (req, res) => {
|
||||||
|
try {
|
||||||
|
const { idapp } = req.params;
|
||||||
|
const { tables } = req.body; // { users: { lastSync: 0 }, groups: { lastSync: 123456 } }
|
||||||
|
|
||||||
|
const results = await SyncManager.sync(tables, idapp, req.user);
|
||||||
|
|
||||||
|
res.json({
|
||||||
|
success: true,
|
||||||
|
data: results,
|
||||||
|
serverTime: Date.now()
|
||||||
|
});
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Sync error:', error);
|
||||||
|
res.status(500).json({
|
||||||
|
success: false,
|
||||||
|
error: error.message
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = router;
|
||||||
125
src/services/SyncManager.js
Normal file
125
src/services/SyncManager.js
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
// server/services/SyncManager.js
|
||||||
|
class SyncManager {
|
||||||
|
constructor() {
|
||||||
|
this.syncConfig = {
|
||||||
|
resps: {
|
||||||
|
model: 'User',
|
||||||
|
method: 'getusersRespList',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['idapp'] // parametri necessari
|
||||||
|
},
|
||||||
|
workers: {
|
||||||
|
model: 'User',
|
||||||
|
method: 'getusersWorkersList',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['idapp']
|
||||||
|
},
|
||||||
|
groups: {
|
||||||
|
model: 'Group',
|
||||||
|
method: 'findAllIdApp',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['idapp']
|
||||||
|
},
|
||||||
|
mygroups: {
|
||||||
|
model: 'MyGroup',
|
||||||
|
method: 'findAllGroups',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['idapp']
|
||||||
|
},
|
||||||
|
products: {
|
||||||
|
model: 'Product',
|
||||||
|
method: 'findAllIdApp',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['idapp']
|
||||||
|
},
|
||||||
|
cart: {
|
||||||
|
model: 'Cart',
|
||||||
|
method: 'getCartByUserId',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['userId', 'idapp'],
|
||||||
|
requiresAuth: true
|
||||||
|
},
|
||||||
|
orderscart: {
|
||||||
|
model: 'OrdersCart',
|
||||||
|
method: 'getOrdersCartByUserId',
|
||||||
|
trackChanges: true,
|
||||||
|
params: ['userId', 'idapp'],
|
||||||
|
requiresAuth: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async sync(syncRequest, idapp, user) {
|
||||||
|
const results = {};
|
||||||
|
const timestamp = Date.now();
|
||||||
|
|
||||||
|
for (const [tableName, params] of Object.entries(syncRequest)) {
|
||||||
|
const config = this.syncConfig[tableName];
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
console.warn(`Tabella ${tableName} non configurata`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Controlla autenticazione
|
||||||
|
if (config.requiresAuth && !user) {
|
||||||
|
results[tableName] = {
|
||||||
|
data: null,
|
||||||
|
timestamp: timestamp,
|
||||||
|
fullSync: true
|
||||||
|
};
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = await this.fetchTableData(
|
||||||
|
tableName,
|
||||||
|
config,
|
||||||
|
params.lastSync,
|
||||||
|
idapp,
|
||||||
|
user
|
||||||
|
);
|
||||||
|
|
||||||
|
results[tableName] = {
|
||||||
|
data: data,
|
||||||
|
timestamp: timestamp,
|
||||||
|
fullSync: params.lastSync === 0 || !config.trackChanges
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Errore sync ${tableName}:`, error);
|
||||||
|
results[tableName] = {
|
||||||
|
error: error.message,
|
||||||
|
timestamp: timestamp
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchTableData(tableName, config, lastSync, idapp, user) {
|
||||||
|
const ModelClass = require(`../models/${config.model}`);
|
||||||
|
|
||||||
|
// Prepara parametri
|
||||||
|
const args = config.params.map(param => {
|
||||||
|
if (param === 'idapp') return idapp;
|
||||||
|
if (param === 'userId') return user?._id.toString() || '0';
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Prima sync o no trackChanges: tutti i dati
|
||||||
|
if (!config.trackChanges || lastSync === 0) {
|
||||||
|
return await ModelClass[config.method](...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync incrementale
|
||||||
|
const query = {
|
||||||
|
idapp: idapp,
|
||||||
|
updatedAt: { $gt: new Date(parseInt(lastSync)) }
|
||||||
|
};
|
||||||
|
|
||||||
|
return await ModelClass.find(query).lean();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = new SyncManager();
|
||||||
@@ -3331,11 +3331,13 @@ module.exports = {
|
|||||||
|
|
||||||
if (params.sortBy && !params.searchByBoundariesMap) {
|
if (params.sortBy && !params.searchByBoundariesMap) {
|
||||||
// maybe we want to sort by blog title or something
|
// maybe we want to sort by blog title or something
|
||||||
const mysort = { $sort: params.sortBy };
|
const mysort = params.sortBy && Object.keys(params.sortBy).length > 0 ? { $sort: params.sortBy } : {};
|
||||||
// console.log('sortBy', params.sortBy);
|
// console.log('sortBy', params.sortBy);
|
||||||
// console.table(mysort);
|
// console.table(mysort);
|
||||||
|
if (mysort.$sort) {
|
||||||
query.push(mysort);
|
query.push(mysort);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
query.push(
|
query.push(
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user