/* Account is a User's single Circuit */ const mongoose = require('mongoose').set('debug', false); const Schema = mongoose.Schema; mongoose.Promise = global.Promise; mongoose.level = 'F'; const tools = require('../tools/general'); const { ObjectId } = require('mongodb'); const shared_consts = require('../tools/shared_nodejs'); // Resolving error Unknown modifier: $pushAll mongoose.plugin((schema) => { schema.options.usePushEach = true; }); const AccountSchema = new Schema({ _id: { type: String, default: function () { return new ObjectId().toString(); }, }, idapp: { type: String, }, numtransactions: { type: Number, }, username: { type: String, }, groupname: { // For the Groups type: String, }, contocom: { // For the Conto Comunitario dei Circuiti type: String, }, circuitId: { // ----- REF TO Circuit type: String, }, name: { type: String, }, deperibile: { type: Boolean, }, fidoConcesso: { type: Number, }, qta_maxConcessa: { type: Number, }, importo_iniziale: { type: Number, default: 0, }, saldo: { type: Number, default: 0, }, totTransato: { type: Number, default: 0, }, saldo_pend: { type: Number, default: 0, }, totTransato_pend: { type: Number, default: 0, }, regulation_ok: { type: Boolean, }, deleted: { type: Boolean, default: false, }, date_created: { type: Date, default: Date.now, }, date_updated: { type: Date, }, }); AccountSchema.statics.findAllIdApp = async function (idapp) { const Account = this; const myfind = { idapp, deleted: false }; return await Account.find(myfind).lean(); }; AccountSchema.pre('save', async function (next) { if (this.isNew) { this._id = new ObjectId().toString(); } next(); }); AccountSchema.statics.getFieldsForSearch = function () { return [ { field: 'name', type: tools.FieldType.string }, { field: 'username', type: tools.FieldType.string }, { field: 'groupname', type: tools.FieldType.string }, { field: 'contocom', type: tools.FieldType.string }, ]; }; AccountSchema.statics.executeQueryTable = function (idapp, params) { params.fieldsearch = this.getFieldsForSearch(); return tools.executeQueryTable(this, idapp, params); }; AccountSchema.statics.getAccountsByUsername = async function (idapp, username) { const Account = this; if (username === undefined) return false; const myquery = { idapp: idapp, username: username, }; return await Account.find(myquery).lean(); }; AccountSchema.statics.calcTotCircolante = async function (idapp, circuitId) { const Account = this; try { let aggr1 = [ { $match: { idapp, circuitId, saldo: { $gt: 0 } }, }, { $group: { _id: null, count: { $sum: '$saldo' } } }, ]; const ris = await Account.aggregate(aggr1); return ris ? ris[0].count : 0; } catch (e) { console.error('err', e); } }; AccountSchema.methods.calcPending = async function (mittente) { try { const account = this; const { SendNotif } = require('../models/sendnotif'); const { Circuit } = require('../models/circuit'); // *** Calc Pending Transactions *** const circuit = await Circuit.getCircuitById(account.circuitId); if (circuit) { let prec_saldo_pend = account.saldo_pend; let prec_totTransato_pend = account.totTransato_pend; let transatopending = 0; if (mittente) { let pendingtransactionsMittente = await SendNotif.getSumPendingTransactionsMittente( account.idapp, account.username, circuit.name, account.groupname ); let saldopendingMitt = pendingtransactionsMittente.reduce((sum, rec) => sum + rec.extrarec.qty, 0); transatopending = pendingtransactionsMittente.reduce((sum, rec) => sum + Math.abs(rec.extrarec.qty), 0); account.saldo_pend = account.saldo - saldopendingMitt; } else { // let pendingtransactionsDest = await SendNotif.getSumPendingTransactionsMittente(account.idapp, account.username, circuit.name, account.groupname); // let saldopendingDest = pendingtransactionsDest.reduce((sum, rec) => sum + rec.extrarec.qty, 0); // transatopending = pendingtransactionsDest.reduce((sum, rec) => sum + Math.abs(rec.extrarec.qty), 0); // account.saldo_pend = account.saldo + saldopendingDest; account.saldo_pend = account.saldo; } account.totTransato_pend = account.totTransato + transatopending; if (prec_saldo_pend !== account.saldo_pend || prec_totTransato_pend !== account.totTransato_pend) { const myaccountupdate = { saldo_pend: account.saldo_pend, totTransato_pend: account.totTransato_pend, }; // Update Record return await Account.findByIdAndUpdate(account.id, { $set: myaccountupdate, }) .then((ris) => { console.log('calcPending', ris); }) .catch((err) => { console.error('calcPending', err); }); } } // ----- } catch (e) { console.error(e); } }; AccountSchema.statics.addtoSaldo = async function (myaccount, amount, mitt) { const Account = this; try { let myaccountupdate = {}; if (myaccount) { myaccount.saldo = myaccount.saldo + amount; if (!myaccount.totTransato) { myaccount.totTransato = 0; } myaccount.totTransato += Math.abs(amount); if (!myaccount.numtransactions) myaccount.numtransactions = 0; myaccount.numtransactions++; myaccount.date_updated = new Date(); myaccountupdate.saldo = myaccount.saldo; myaccountupdate.totTransato = myaccount.totTransato; myaccountupdate.numtransactions = myaccount.numtransactions; myaccountupdate.date_updated = myaccount.date_updated; const ris = await Account.updateOne( { _id: myaccount.id }, { $set: myaccountupdate, } ); // Calcola Saldo Pendente ! await myaccount.calcPending(true); const recupdated = await Account.findOne({ _id: myaccount.id }); return recupdated; } } catch (e) { console.error('error', e); } return null; }; AccountSchema.pre('save', async function (next) { if (this.isNew) { if (!this.date_created) this.date_created = new Date(); } next(); }); AccountSchema.statics.getAccountByUsernameAndCircuitId = async function ( idapp, username, circuitId, createifnotexist, confido, groupname = '', contocom = '' ) { const Account = this; try { const { Circuit } = require('../models/circuit'); // if (username === undefined) // return false; let myquery = { idapp, circuitId, }; if (groupname) { myquery.groupname = groupname; } else if (contocom) { myquery.contocom = contocom; } else { myquery.username = username; } let mycircuit = await Circuit.getCircuitById(circuitId); if (mycircuit) { let myaccount = await Account.findOne(myquery); if (!myaccount && createifnotexist) { myaccount = new Account({ _id: new ObjectId().toString(), idapp, username: !groupname && !contocom ? username : '', groupname, contocom, circuitId: mycircuit._id, deperibile: false, importo_iniziale: 0, saldo: 0, saldo_pend: 0, fidoConcesso: 0, qta_maxConcessa: 0, totTransato: 0, numtransactions: 0, totTransato_pend: 0, }); if (contocom) { myaccount.fidoConcesso = mycircuit.fido_scoperto_default_contocom || shared_consts.CIRCUIT_PARAMS.SCOPERTO_MIN_CONTO_COMUNITARIO; myaccount.qta_maxConcessa = mycircuit.qta_max_default_contocom || shared_consts.CIRCUIT_PARAMS.SCOPERTO_MAX_CONTO_COMUNITARIO; } else { if (!mycircuit.fido_scoperto_default_grp) mycircuit.fido_scoperto_default_grp = shared_consts.CIRCUIT_PARAMS.SCOPERTO_MIN_GRP; if (!mycircuit.qta_max_default_grp) mycircuit.qta_max_default_grp = shared_consts.CIRCUIT_PARAMS.SCOPERTO_MAX_GRP; if (groupname) { myaccount.fidoConcesso = mycircuit.fido_scoperto_default_grp; myaccount.qta_maxConcessa = mycircuit.qta_max_default_grp; } else { myaccount.fidoConcesso = mycircuit.fido_scoperto_default; myaccount.qta_maxConcessa = mycircuit.qta_max_default; } } if (!confido) { myaccount.fidoConcesso = 0; } let acc = await myaccount.save(); if (mycircuit.creditodiPartenza && mycircuit.creditodiPartenza > 0) { acc = await Account.addtoSaldo(acc, mycircuit.creditodiPartenza, false); } return acc; } return myaccount; } return null; } catch (e) { console.error('error', e); } }; AccountSchema.statics.isExistAccountByUsernameAndCircuitId = async function ( idapp, username, circuitId, groupname = '', contocom = '' ) { const Account = this; try { const { Circuit } = require('../models/circuit'); if (username === undefined) return false; let myquery = { idapp, circuitId, }; if (groupname) { myquery.groupname = groupname; } else if (contocom) { myquery.contocom = contocom; } else { myquery.username = username; } let mycircuit = await Circuit.getCircuitById(circuitId); if (mycircuit) { let myaccount = await Account.findOne(myquery); return !!myaccount; } return false; } catch (e) { console.error('error', e); } }; AccountSchema.statics.createAccount = async function ( idapp, username, circuitName, confido, groupname = '', contocom = '' ) { const { Circuit } = require('../models/circuit'); try { mycircuit = await Circuit.findOne({ name: circuitName }, { _id: 1 }); if (mycircuit) { return await Account.getAccountByUsernameAndCircuitId( idapp, username, mycircuit._id, true, confido, groupname, contocom ); } else { return null; } } catch (e) { console.error('error', e); return null; } }; AccountSchema.statics.getUserAccounts = async function (idapp, username) { const { SendNotif } = require('../models/sendnotif'); try { let aggr1 = [ { $match: { idapp, username }, }, { $lookup: { from: 'circuits', localField: 'circuitId', foreignField: '_id', as: 'circuit', }, }, { $unwind: '$circuit' }, { $lookup: { from: 'sendnotifs', as: 'notifspending', let: { circuitname: '$circuit.name', username: '$username', idapp: '$idapp', typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS, typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ, }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ['$idapp', '$$idapp'] }, { $eq: ['$typedir', '$$typedir'] }, { $eq: ['$typeid', '$$typeid'] }, { $eq: ['$status', 0] }, { $eq: ['$sender', '$$username'] }, { $eq: ['$extrarec.circuitname', '$$circuitname'] }, ], }, }, }, { $group: { _id: '$extrarec.notifIdToUpdate', result: { $first: '$$ROOT' } }, }, ], }, }, ]; const ris = await this.aggregate(aggr1); // console.log('1 - INIZIA getUserAccounts ') // console.log(aggr1); /* if (ris) { for (const account of ris) { try { //++OTTIMIZZARE QUESTA PARTE ! (CON UNA QUERY...) // console.log(' 1B - PENDIND... ') let pendingtransactions = await SendNotif.getSumPendingTransactions(idapp, username, account.circuit.name); let saldopending = pendingtransactions.reduce((sum, rec) => sum + rec.extrarec.qty, 0); if (saldopending !== 0) { account.saldo -= saldopending; account.totTransato = account.totTransato || 0; } } catch (e) { console.error('getUserAccounts 1) ', e); } } } */ return ris; } catch (e) { console.error('getUserAccounts', e); } }; AccountSchema.statics.getGroupAccounts = async function (idapp, groupname) { if (!groupname) { return []; } try { let aggr1 = [ { $match: { idapp, groupname }, }, { $lookup: { from: 'circuits', localField: 'circuitId', foreignField: '_id', as: 'circuit', }, }, { $unwind: '$circuit' }, { $lookup: { from: 'sendnotifs', as: 'notifspending', let: { circuitname: '$circuit.name', groupname: '$groupname', idapp: '$idapp', typedir: shared_consts.TypeNotifs.TYPEDIR_CIRCUITS, typeid: shared_consts.TypeNotifs.ID_CIRCUIT_SENDCOINSREQ, }, pipeline: [ { $match: { $expr: { $and: [ { $eq: ['$typedir', '$$typedir'] }, { $eq: ['$typeid', '$$typeid'] }, { $eq: ['$status', 0] }, { $eq: ['$sendergroup', '$$groupname'] }, { $eq: ['$idapp', '$$idapp'] }, { $eq: ['$extrarec.circuitname', '$$circuitname'] }, ], }, }, }, { $group: { _id: '$extrarec.notifIdToUpdate', result: { $first: '$$ROOT' } }, }, ], }, }, ]; const ris = await this.aggregate(aggr1); return ris; } catch (e) { console.error('e', e); } }; // Imposta a tutti i Conti Collettivi, i seguenti minimi e massimi AccountSchema.statics.SetMinMaxCollettivi = async function (idapp, valmin, valmax) { const Account = this; const ris = await Account.updateMany( { idapp, groupname: { $nin: [null, ''] } }, { $set: { fidoConcesso: valmin, qta_maxConcessa: valmax, }, } ); }; // Imposta a tutti i Conti Comunitari, i seguenti minimi e massimi AccountSchema.statics.SetMinMaxComunitari = async function (idapp, valmin, valmax) { const Account = this; const ris = await Account.updateMany( { idapp, contocom: { $nin: [null, ''] } }, { $set: { fidoConcesso: valmin, qta_maxConcessa: valmax, }, } ); }; // Imposta a tutti i Conti Personali, i seguenti minimi e massimi AccountSchema.statics.SetMinMaxPersonali = async function (idapp, fidoConcesso, qta_maxConcessa, circuitId) { const Account = this; if (circuitId) { const ris = await Account.updateMany( { idapp, circuitId, fidoConcesso: { $gt: 0 }, username: { $nin: [null, ''] } }, { $set: { fidoConcesso, qta_maxConcessa, }, } ); const circuit = await Circuit.findOne({ _id: circuitId }); if (!circuit.circuitoIndipendente) { // Se aggiorno questi dati, e non รจ un Circuito Indipendente, allora devo aggiornare anche gli account del RIS Nazionale await Account.updateAccountCircuitoItaliaByLimiti(idapp, circuitId, fidoConcesso, qta_maxConcessa); } } else { const ris = await Account.updateMany( { idapp, fidoConcesso: { $gt: 0 }, username: { $nin: [null, ''] } }, { $set: { fidoConcesso, qta_maxConcessa, }, } ); } }; AccountSchema.statics.updateFido = async function (idapp, username, groupname, circuitId, fido) { let paramstoupdate = { fidoConcesso: fido, }; let risult = null; if (groupname) risult = await Account.updateOne({ idapp, circuitId, groupname }, { $set: paramstoupdate }); else risult = await Account.updateOne({ idapp, username, circuitId }, { $set: paramstoupdate }); return risult; }; AccountSchema.statics.updateQtaMax = async function (idapp, username, groupname, circuitId, qtamax) { let paramstoupdate = { qta_maxConcessa: qtamax, }; let risult = null; if (groupname) risult = await Account.updateOne({ idapp, circuitId, groupname }, { $set: paramstoupdate }); else risult = await Account.updateOne({ idapp, username, circuitId }, { $set: paramstoupdate }); return risult && risult.modifiedCount > 0; }; AccountSchema.statics.getAccountsCircuitiExtraProvinciali = async function (idapp) { const { Circuit } = require('../models/circuit'); const circuits = await Circuit.getCircuitiExtraProvinciali(idapp); if (circuits.length > 0) { const circuitIds = circuits.map((circuit) => circuit._id); return Account.find({ idapp, circuitId: { $in: circuitIds } }); } }; AccountSchema.statics.getAccountsCircuitoItalia = async function (idapp) { const { Circuit } = require('../models/circuit'); const circuit = await Circuit.getCircuitoItalia(idapp); if (circuit) { return Account.find({ idapp, circuitId: circuit._id }); } }; AccountSchema.statics.updateAccountCircuitoItaliaByLimiti = async function ( idapp, circuitId, fidoConcesso, qta_maxConcessa ) { const { Circuit } = require('../models/circuit'); try { const accounts = await this.getAccountsCircuitoItalia(idapp); for (const account of accounts) { const circuitId = account.circuitId; const circuit = await Circuit.findOne({ _id: circuitId }); if (circuit) { let fido = 0; let qtamax = 0; if (account.groupname) { fido = circuit.fido_scoperto_default_grp * shared_consts.CIRCUIT_CFG.MULT_FIDO_GROUP; qtamax = circuit.qta_max_default_grp * shared_consts.CIRCUIT_CFG.MULT_FIDO_GROUP; } else { fido = circuit.fido_scoperto_default * shared_consts.CIRCUIT_CFG.MULT_FIDO_USER; qtamax = circuit.qta_max_default * shared_consts.CIRCUIT_CFG.MULT_FIDO_USER; } let paramstoupdate = { fidoConcesso: fido, qta_maxConcessa: qtamax, }; risult = await Account.updateOne({ _id: account.id }, { $set: paramstoupdate }); } } return risult; } catch (e) { console.error('updateAccountCircuitoItaliaByLimiti', e); } return false; }; AccountSchema.statics.canEditAccountAdmins = async function (username, id) { const account = await Account.findOne({ _id: id }).lean(); const { Circuit } = require('../models/circuit'); if (account) { const circuit = await Circuit.findOne({ _id: account.circuitId }).lean(); if (circuit) { return circuit.admins.findIndex((admin) => admin.username === username) >= 0; } } return false; }; AccountSchema.statics.addToPeopleOfMyAccount = async function (idapp, username, circuitId, person_username, perm) { return await Account.updateOne( { idapp, username, circuitId }, { $push: { people: { username: person_username, perm, date: new Date(), }, }, } ); }; // Rimuovi dagli Admin del Account AccountSchema.statics.removeAdminOfAccount = async function (idapp, username, circuitId, person_username, perm) { const { Circuit } = require('../models/circuit'); return await Circuit.updateOne( { idapp, username, circuitId }, { $pull: { people: { username: { $in: [person_username] } } } } ); }; // Rimuovi l'account AccountSchema.statics.removeAccount = async function (accountId) { return await Account.deleteOne({ _id: accountId }); }; AccountSchema.statics.updateSaldoAndTransato_AllAccounts = async function (idapp) { const recaccounts = await Account.find({ idapp }); for (const account of recaccounts) { await account.calcPending(); } }; const Account = mongoose.model('Account', AccountSchema); Account.createIndexes() .then(() => {}) .catch((err) => { throw err; }); module.exports = { Account };