From 6fe3ed7c8b6980c09d20873cea6324ea5be82669 Mon Sep 17 00:00:00 2001 From: Surya Paolo Date: Tue, 2 Dec 2025 22:16:29 +0100 Subject: [PATCH] - aggiornamenti guida RIS, FAQ - Editor HTML aggiunto CSS e Script - Statistiche - CRISBalanceBar - Inizio Sync... (ma disattivato) --- src/models/user.js | 1050 ++++++++++++++++++----------------- src/populate/sectorgoods.js | 40 +- src/routes/sync.js | 29 + src/services/SyncManager.js | 125 +++++ src/tools/general.js | 6 +- 5 files changed, 717 insertions(+), 533 deletions(-) create mode 100644 src/routes/sync.js create mode 100644 src/services/SyncManager.js diff --git a/src/models/user.js b/src/models/user.js index b1704e0..580c16f 100755 --- a/src/models/user.js +++ b/src/models/user.js @@ -40,547 +40,554 @@ mongoose.plugin((schema) => { mongoose.set('debug', false); -const UserSchema = new mongoose.Schema({ - userId: { - type: String, - }, - email: { - type: String, - // required: true, - trim: true, - minlength: 1, - unique: false, - /*validate: { +const UserSchema = new mongoose.Schema( + { + userId: { + type: String, + }, + email: { + type: String, + // required: true, + trim: true, + minlength: 1, + unique: false, + /*validate: { validator: validator.isEmail, message: '{VALUE} is not a valid email' }*/ - }, - hash: { - type: String, - }, - idapp: { - type: String, - required: true, - }, - idMyGroup: { - type: String, - }, - group: { - type: Number, - }, - index: { - type: Number, - }, - ind_order: { - type: Number, - }, - old_order: { - type: Number, - }, - username: { - type: String, - required: true, - trim: true, - minlength: 3, - unique: false, - }, - name: { - type: String, - trim: true, - }, - surname: { - type: String, - trim: true, - }, - password: { - type: String, - require: true, - minlength: 6, - }, - old_password: { - type: String, - require: false, - }, - lang: { - type: String, - require: true, - }, - linkreg: { - type: String, - required: false, - }, - verified_email: { - type: Boolean, - }, - lasttime_email_sent_verify: { - type: Date, - }, - made_gift: { - type: Boolean, - }, - tokens: [ - { - access: { - type: String, - required: true, + }, + hash: { + type: String, + }, + idapp: { + type: String, + required: true, + }, + idMyGroup: { + type: String, + }, + group: { + type: Number, + }, + index: { + type: Number, + }, + ind_order: { + type: Number, + }, + old_order: { + type: Number, + }, + username: { + type: String, + required: true, + trim: true, + minlength: 3, + unique: false, + }, + name: { + type: String, + trim: true, + }, + surname: { + type: String, + trim: true, + }, + password: { + type: String, + require: true, + minlength: 6, + }, + old_password: { + type: String, + require: false, + }, + lang: { + type: String, + require: true, + }, + linkreg: { + type: String, + required: false, + }, + verified_email: { + type: Boolean, + }, + lasttime_email_sent_verify: { + type: Date, + }, + made_gift: { + type: Boolean, + }, + tokens: [ + { + access: { + type: String, + required: true, + }, + browser: { + type: String, + required: true, + }, + token: { + type: String, + required: true, + }, + refreshToken: { + type: String, + default: '', + }, + browser_random: { + type: String, + default: '', + }, + date_login: { + type: Date, + }, }, - browser: { + ], + perm: { + type: Number, + }, + ipaddr: { + type: String, + }, + banIp: { + type: Boolean, + }, + date_reg: { + type: Date, + }, + date_deleted: { + type: Date, + }, + date_tokenforgot: { + type: Date, + }, + tokenforgot: { + type: String, + }, + tokenforgot_code: { + type: String, + }, + retry_pwd: { + type: Number, + default: 0, + }, + date_tokenreg: { + type: Date, + }, + tokenreg: { + type: String, + }, + lasttimeonline: { + type: Date, + }, + useragent: { + type: String, + }, + news_on: { + type: Boolean, + }, + diario_on: { + type: Boolean, + }, + test: { + type: Boolean, + }, + email_errata: { + type: Boolean, + }, + lastid_newstosent: { + type: String, + }, + aportador_solidario: { + type: String, + }, + verified_by_aportador: { + type: Boolean, + }, + token_da_ammettere: { + type: String, + }, + date_token_ammettere: { + type: Date, + }, + notask_verif: { + type: Boolean, + }, + trust_modified: { + type: Date, + }, + aportador_iniziale: { + type: String, + }, + aportador_solidario_nome_completo: { + type: String, + }, + aportador_solidario_ind_order: { + type: Number, + }, + deleted: { + type: Boolean, + default: false, + }, + deletedAt: Date, + sospeso: { + type: Boolean, + }, + blocked: { + type: Boolean, + }, + username_who_block: { + type: String, + }, + date_blocked: { + type: Date, + }, + reported: { + type: Boolean, + }, + username_who_report: { + type: String, + }, + date_report: { + type: Date, + }, + non_voglio_imbarcarmi: { + type: Boolean, + }, + navinonpresenti: { + type: Boolean, + }, + subaccount: { + type: Boolean, + }, + cart: { + type: Object, + }, + profile: { + img: { type: String, - required: true, }, - token: { + nationality: { type: String, - required: true, }, - refreshToken: { + intcode_cell: { type: String, - default: '', }, - browser_random: { + iso2_cell: { type: String, - default: '', }, - date_login: { + cell: { + type: String, + }, + country_pay: { + type: String, + }, + email_paypal: { + type: String, + }, + payeer_id: { + type: String, + }, + advcash_id: { + type: String, + }, + revolut: { + type: String, + }, + link_payment: { + type: String, + }, + note_payment: { + type: String, + }, + paymenttypes: [], + username_telegram: { + type: String, + }, + firstname_telegram: { + type: String, + }, + lastname_telegram: { + type: String, + }, + telegram_verification_skipped: { + type: Boolean, + }, + telegram_verification_token: { + type: String, + }, + telegram_verification_expires: { + type: String, + }, + website: { + type: String, + }, + teleg_id: { + type: Number, + }, + teleg_id_old: { + type: Number, + }, + teleg_checkcode: { + type: Number, + }, + manage_telegram: { + type: Boolean, + }, + admin_telegram: { + type: Boolean, + }, + resplist: { + type: Boolean, + }, + workerslist: { + type: Boolean, + }, + dateofbirth: { type: Date, }, - }, - ], - perm: { - type: Number, - }, - ipaddr: { - type: String, - }, - banIp: { - type: Boolean, - }, - date_reg: { - type: Date, - }, - date_deleted: { - type: Date, - }, - date_tokenforgot: { - type: Date, - }, - tokenforgot: { - type: String, - }, - tokenforgot_code: { - type: String, - }, - retry_pwd: { - type: Number, - default: 0, - }, - date_tokenreg: { - type: Date, - }, - tokenreg: { - type: String, - }, - lasttimeonline: { - type: Date, - }, - useragent: { - type: String, - }, - news_on: { - type: Boolean, - }, - diario_on: { - type: Boolean, - }, - test: { - type: Boolean, - }, - email_errata: { - type: Boolean, - }, - lastid_newstosent: { - type: String, - }, - aportador_solidario: { - type: String, - }, - verified_by_aportador: { - type: Boolean, - }, - token_da_ammettere: { - type: String, - }, - date_token_ammettere: { - type: Date, - }, - notask_verif: { - type: Boolean, - }, - trust_modified: { - type: Date, - }, - aportador_iniziale: { - type: String, - }, - aportador_solidario_nome_completo: { - type: String, - }, - aportador_solidario_ind_order: { - type: Number, - }, - deleted: { - type: Boolean, - default: false, - }, - sospeso: { - type: Boolean, - }, - blocked: { - type: Boolean, - }, - username_who_block: { - type: String, - }, - date_blocked: { - type: Date, - }, - reported: { - type: Boolean, - }, - username_who_report: { - type: String, - }, - date_report: { - type: Date, - }, - non_voglio_imbarcarmi: { - type: Boolean, - }, - navinonpresenti: { - type: Boolean, - }, - subaccount: { - type: Boolean, - }, - cart: { - type: Object, - }, - profile: { - img: { - type: String, - }, - nationality: { - type: String, - }, - intcode_cell: { - type: String, - }, - iso2_cell: { - type: String, - }, - cell: { - type: String, - }, - country_pay: { - type: String, - }, - email_paypal: { - type: String, - }, - payeer_id: { - type: String, - }, - advcash_id: { - type: String, - }, - revolut: { - type: String, - }, - link_payment: { - type: String, - }, - note_payment: { - type: String, - }, - paymenttypes: [], - username_telegram: { - type: String, - }, - firstname_telegram: { - type: String, - }, - lastname_telegram: { - type: String, - }, - telegram_verification_skipped: { - type: Boolean, - }, - telegram_verification_token: { - type: String, - }, - telegram_verification_expires: { - type: String, - }, - website: { - type: String, - }, - teleg_id: { - type: Number, - }, - teleg_id_old: { - type: Number, - }, - teleg_checkcode: { - type: Number, - }, - manage_telegram: { - type: Boolean, - }, - admin_telegram: { - type: Boolean, - }, - resplist: { - type: Boolean, - }, - workerslist: { - type: Boolean, - }, - dateofbirth: { - type: Date, - }, - born_city: { - type: String, - trim: true, - }, - born_city_id: { - type: Number, - }, - born_province: { - type: String, - trim: true, - }, - born_country: { - type: String, - trim: true, - }, - my_dream: { - type: String, - }, - saw_and_accepted: { - type: Number, - }, - saw_zoom_presentation: { - type: Boolean, - }, - ask_zoom_partecipato: { - type: Boolean, - }, - qualified: { - type: Boolean, - }, - qualified_2invitati: { - type: Boolean, - }, - special_req: { - type: Boolean, - }, - sex: { - type: Number, - }, - biografia: { - type: String, - }, - note: { - type: String, - }, - da_contattare: { - type: Boolean, - }, - qualifica: { - type: String, - }, - motivazioni: { - type: String, - }, - competenze_professionalita: { - type: String, - }, - cosa_offrire: { - type: String, - }, - cosa_ricevere: { - type: String, - }, - altre_comunicazioni: { - type: Boolean, - }, - come_ci_hai_conosciuto: { - type: Boolean, - }, - socio: { - type: Boolean, - }, - socioresidente: { - type: Boolean, - }, - consiglio: { - type: Boolean, - }, - myshares: [ - { - description: { type: String }, - rating: { type: Number }, + born_city: { + type: String, + trim: true, }, - ], - friends: [ - { - _id: false, - username: { type: String }, - date: { type: Date }, + born_city_id: { + type: Number, }, - ], // username - req_friends: [ - { - _id: false, - username: { type: String }, - date: { type: Date }, + born_province: { + type: String, + trim: true, }, - ], // username - handshake: [ - { - _id: false, - username: { type: String }, - date: { type: Date }, + born_country: { + type: String, + trim: true, }, - ], // username - mygroups: [ - { - _id: false, - groupname: { type: String }, - date: { type: Date }, + my_dream: { + type: String, }, - ], + saw_and_accepted: { + type: Number, + }, + saw_zoom_presentation: { + type: Boolean, + }, + ask_zoom_partecipato: { + type: Boolean, + }, + qualified: { + type: Boolean, + }, + qualified_2invitati: { + type: Boolean, + }, + special_req: { + type: Boolean, + }, + sex: { + type: Number, + }, + biografia: { + type: String, + }, + note: { + type: String, + }, + da_contattare: { + type: Boolean, + }, + qualifica: { + type: String, + }, + motivazioni: { + type: String, + }, + competenze_professionalita: { + type: String, + }, + cosa_offrire: { + type: String, + }, + cosa_ricevere: { + type: String, + }, + altre_comunicazioni: { + type: Boolean, + }, + come_ci_hai_conosciuto: { + type: Boolean, + }, + socio: { + type: Boolean, + }, + socioresidente: { + type: Boolean, + }, + consiglio: { + type: Boolean, + }, + myshares: [ + { + description: { type: String }, + rating: { type: Number }, + }, + ], + friends: [ + { + _id: false, + username: { type: String }, + date: { type: Date }, + }, + ], // username + req_friends: [ + { + _id: false, + username: { type: String }, + date: { type: Date }, + }, + ], // username + handshake: [ + { + _id: false, + username: { type: String }, + date: { type: Date }, + }, + ], // username + mygroups: [ + { + _id: false, + groupname: { type: String }, + date: { type: Date }, + }, + ], - mycircuits: [ - { - _id: false, - circuitname: { type: String }, - date: { type: Date }, - token: { type: String }, - }, - ], - last_circuitpath: { - type: String, - }, - lastdate_reqRis: { - type: Date, - }, - lastdate_LinkReg: { - type: Date, - }, - notifs: [ - { - _id: false, - dir: { type: Number }, - value: { type: Number }, - }, - ], - notif_idCities: [ - { - type: Number, - }, - ], - notif_provinces: [ - { + mycircuits: [ + { + _id: false, + circuitname: { type: String }, + date: { type: Date }, + token: { type: String }, + }, + ], + last_circuitpath: { type: String, }, - ], - notif_regions: [ - { + lastdate_reqRis: { + type: Date, + }, + lastdate_LinkReg: { + type: Date, + }, + notifs: [ + { + _id: false, + dir: { type: Number }, + value: { type: Number }, + }, + ], + notif_idCities: [ + { + type: Number, + }, + ], + notif_provinces: [ + { + type: String, + }, + ], + notif_regions: [ + { + type: String, + }, + ], + notif_sectors: [ + { + type: Number, + }, + ], + notif_sector_goods: [ + { + type: Number, + }, + ], + resid_prov_id: { + type: Number, + }, + resid_comune: { type: String, + trim: true, + default: '', }, - ], - notif_sectors: [ - { + resid_str_comune: { + type: String, + trim: true, + default: '', + }, + resid_province: { + type: String, + trim: true, + }, + resid_card: { + type: String, + trim: true, + }, + stepTutorial: { type: Number, }, - ], - notif_sector_goods: [ - { - type: Number, + noNameSurname: { + type: Boolean, }, - ], - resid_prov_id: { - type: Number, - }, - resid_comune: { - type: String, - trim: true, - default: '', - }, - resid_str_comune: { - type: String, - trim: true, - default: '', - }, - resid_province: { - type: String, - trim: true, - }, - resid_card: { - type: String, - trim: true, - }, - stepTutorial: { - type: Number, - }, - noNameSurname: { - type: Boolean, - }, - noCircuit: { - type: Boolean, - }, - noComune: { - type: Boolean, - }, - noCircIta: { - type: Boolean, - }, - noFoto: { - type: Boolean, - }, - seen: [ - { - _id: false, - id: { type: String }, - tab: { type: Number }, + noCircuit: { + type: Boolean, }, - ], - bookmark: [ - { - _id: false, - id: { type: String }, - tab: { type: Number }, + noComune: { + type: Boolean, }, - ], - favorite: [ - { - _id: false, - id: { type: String }, - tab: { type: Number }, + noCircIta: { + type: Boolean, }, - ], - attend: [ - { - _id: false, - id: { type: String }, - tab: { type: Number }, - num: { type: Number }, + noFoto: { + type: Boolean, }, - ], - version: { type: Number }, - insert_circuito_ita: { type: Boolean }, + seen: [ + { + _id: false, + id: { type: String }, + tab: { type: Number }, + }, + ], + bookmark: [ + { + _id: false, + id: { type: String }, + tab: { type: Number }, + }, + ], + favorite: [ + { + _id: false, + id: { type: String }, + tab: { type: Number }, + }, + ], + attend: [ + { + _id: false, + id: { type: String }, + tab: { type: Number }, + num: { type: Number }, + }, + ], + version: { type: Number }, + insert_circuito_ita: { type: Boolean }, + }, + updatedAt: { type: Date, default: Date.now }, }, -}); + { + timestamps: true, // Mongoose aggiorna automaticamente updatedAt + } +); UserSchema.methods.toJSON = function () { const user = this; @@ -6960,7 +6967,6 @@ UserSchema.statics.isEnableToReceiveEmailByUsernameECmd = async function (idapp, let ricevo = true; if (cmd === shared_consts.CIRCUITCMD.SETFIDO) { // Controllo se l'utente ha scelto di ricevere l'email - } return ricevo; @@ -6983,6 +6989,28 @@ UserSchema.statics.getTokenByUsernameAndCircuitName = async function (idapp, use 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); 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 = { User, diff --git a/src/populate/sectorgoods.js b/src/populate/sectorgoods.js index c95b7d7..71327c4 100644 --- a/src/populate/sectorgoods.js +++ b/src/populate/sectorgoods.js @@ -1,25 +1,25 @@ module.exports = { list: [ {_id: 1, descr: 'Abbigliamento', icon: 'fas fa-tshirt', color: 'blue-7'}, - {_id: 2, descr: 'Arredamento', icon: 'fas fa-chair', color: 'green-7'}, - {_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'orange-7'}, - {_id: 4, descr: 'Artigianato', icon: 'fas fa-screwdriver', color: 'red-7'}, - {_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'purple-7'}, - {_id: 6, descr: 'Bimbi', icon: 'fas fa-child', color: 'cyan-7'}, - {_id: 7, descr: 'Cibo'}, - {_id: 8, descr: 'Collezionismo e Antiquariato'}, - {_id: 9, descr: 'Elettronica di Consumo'}, + {_id: 2, descr: 'Arredamento', icon: 'fas fa-couch', color: 'brown-7'}, + {_id: 3, descr: 'Auto e Moto', icon: 'fas fa-car', color: 'grey-9'}, + {_id: 4, descr: 'Artigianato', icon: 'fas fa-gem', color: 'amber-7'}, + {_id: 5, descr: 'Bellezza e Igiene', icon: 'fas fa-spa', color: 'pink-7'}, + {_id: 6, descr: 'Bimbi', icon: 'fas fa-baby', color: 'cyan-7'}, + {_id: 7, descr: 'Cibo', icon: 'fas fa-utensils', color: 'orange-7'}, + {_id: 8, descr: 'Collezionismo e Antiquariato', icon: 'fas fa-coins', color: 'brown-9'}, + {_id: 9, descr: 'Elettronica', icon: 'fas fa-laptop', color: 'blue-grey-8'}, {_id: 10, descr: 'Giochi', icon: 'fas fa-gamepad', color: 'purple-7'}, - {_id: 11, descr: 'Hobby', icon: 'fas fa-guitar', color: 'cyan-7'}, - {_id: 12, descr: 'Libri', icon: 'fas fa-book', color: 'indigo-7'}, - {_id: 13, descr: 'Musica e Film', icon: 'fas fa-music', color: 'brown-7'}, - {_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-graduation-cap', color: 'pink-7'}, - {_id: 15, descr: 'Sport', icon: 'fas fa-futbol', color: 'orange-7'}, - {_id: 16, descr: 'Un po\' di Tutto', icon: 'fas fa-globe-europe', color: 'red-7'}, - {_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'blue-7'}, - {_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'green-7'}, - {_id: 19, descr: 'Arte / Decorazioni', icon: 'fas fa-palette', color: 'purple-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-open', color: 'indigo-7'}, + {_id: 13, descr: 'Musica e Film', icon: 'fas fa-film', color: 'deep-purple-7'}, + {_id: 14, descr: 'Scuola e Ufficio', icon: 'fas fa-pen', color: 'blue-8'}, + {_id: 15, descr: 'Sport', icon: 'fas fa-bicycle', color: 'green-8'}, + {_id: 16, descr: 'Varie', icon: 'fas fa-box', color: 'grey-7'}, + {_id: 17, descr: 'Attrezzature', icon: 'fas fa-tools', color: 'grey-8'}, + {_id: 18, descr: 'Animali', icon: 'fas fa-paw', color: 'brown-6'}, + {_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: 21, descr: 'Elettrodomestici', icon: 'fas fa-plug', color: 'blue-grey-7'}, + ], +}; \ No newline at end of file diff --git a/src/routes/sync.js b/src/routes/sync.js new file mode 100644 index 0000000..cbbce4a --- /dev/null +++ b/src/routes/sync.js @@ -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; \ No newline at end of file diff --git a/src/services/SyncManager.js b/src/services/SyncManager.js new file mode 100644 index 0000000..d669e5c --- /dev/null +++ b/src/services/SyncManager.js @@ -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(); \ No newline at end of file diff --git a/src/tools/general.js b/src/tools/general.js index 2e7e08a..158e68a 100755 --- a/src/tools/general.js +++ b/src/tools/general.js @@ -3331,10 +3331,12 @@ module.exports = { if (params.sortBy && !params.searchByBoundariesMap) { // 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.table(mysort); - query.push(mysort); + if (mysort.$sort) { + query.push(mysort); + } } query.push(