From 39c08afb956c493c0dea92339709f38b28cd88a2 Mon Sep 17 00:00:00 2001 From: Paolo Arena Date: Wed, 24 Feb 2021 04:48:31 +0100 Subject: [PATCH] Reportistica Ore 2 --- src/server/config/config.js | 16 +-- src/server/models/hours.js | 132 +++++++++++++++++++++++- src/server/models/project.js | 34 +++++++ src/server/models/user.js | 16 ++- src/server/router/index_router.js | 5 +- src/server/router/projects_router.js | 2 + src/server/router/report_router.js | 144 +++++++++++++++++++++++++++ src/server/router/todos_router.js | 57 +++++++---- src/server/router/users_router.js | 5 + src/server/server.js | 2 + src/server/telegram/telegrambot.js | 4 +- src/server/tools/general.js | 63 ++++++++---- src/server/tools/shared_nodejs.js | 3 + 13 files changed, 427 insertions(+), 56 deletions(-) create mode 100755 src/server/router/report_router.js diff --git a/src/server/config/config.js b/src/server/config/config.js index 77357b8..3843039 100755 --- a/src/server/config/config.js +++ b/src/server/config/config.js @@ -100,7 +100,7 @@ if (process.env.NODE_ENV === 'production') { pathreg_add:'', abilitanave: false, }, - { + /*{ idapp: '7', name: 'Ayni', adminemail: 'ayni.gifteconomy@gmail.com', @@ -115,7 +115,7 @@ if (process.env.NODE_ENV === 'production') { telegram_bot_name: 'notevoleaynibot', pathreg_add:'_ayni', abilitanave: true, - }, + },*/ { idapp: '8', name: 'CentrOlistico Rimini', @@ -159,8 +159,8 @@ if (process.env.NODE_ENV === 'production') { dir: '/var/www/comunitanuovomondo.app', email_from: 'cnmrimini@gmail.com', email_pwd: 'b11837c0cfbf77b84cdbb44ecf9ee4f6b91f12599b76568e6b2b35c2bdb91291baHEPn6Q9wTgMOW29IQB3w==', - telegram_key:'1202788747:AAErwzIsD7k-3Yj5AX6ci3p7ELMuyASq4vA', - telegram_bot_name: 'comunitanuovomondo_bot', + telegram_key:'1646348227:AAF2qgpHB4KprhB0HPefazGLyoVGW_i4jTA', + telegram_bot_name: 'cnm_mybot', pathreg_add:'_cnm', abilitanave: false, }, @@ -261,7 +261,7 @@ if (process.env.NODE_ENV === 'production') { pathreg_add:'', abilitanave: false, }, - { + /*{ idapp: '7', name: 'Ayni (Server Test)', adminemail: 'pao.loarena77@gmail.com', @@ -275,7 +275,7 @@ if (process.env.NODE_ENV === 'production') { telegram_bot_name: 'testnotevoleaynibot', pathreg_add:'_ayni', abilitanave: true, - }, + },*/ { idapp: '8', name: 'CentrOlistico Rimini', @@ -433,7 +433,7 @@ if (process.env.NODE_ENV === 'production') { pathreg_add:'', abilitanave: false, }, - { + /*{ idapp: '7', name: 'Ayni', adminemail: 'paolo.arena77@gmail.com', @@ -447,7 +447,7 @@ if (process.env.NODE_ENV === 'production') { telegram_key:'353996190:AAEcEbfrm_zTK6mBKf8ye9j-PXt958SDxew', pathreg_add:'_ayni', abilitanave: true, - }, + },*/ { idapp: '8', name: 'CentrOlistico Rimini', diff --git a/src/server/models/hours.js b/src/server/models/hours.js index d4a7474..6d5dc8f 100755 --- a/src/server/models/hours.js +++ b/src/server/models/hours.js @@ -12,11 +12,17 @@ mongoose.plugin(schema => { schema.options.usePushEach = true }); +var ObjectId = mongoose.Types.ObjectId; + +const { ObjectID } = require('mongodb'); + const HoursSchema = new Schema({ idapp: { type: String, }, - userId: { type: Schema.Types.ObjectId, ref: 'User' }, + userId: { + type: String + }, descr: { type: String, }, @@ -55,6 +61,127 @@ module.exports.findAllIdApp = async function (idapp) { return await Hours.find(myfind); }; +module.exports.correggiHours = async function (idapp) { + const myfind = { idapp }; + + const myarr = await Hours.find(myfind); + + for (const rec of myarr) { + + rec.userId = rec.userId.toString(); + let ris = await Hours.findOneAndUpdate({ _id: rec._id }, { $set: { userId: rec.userId } }, { new: false } ); + if (!!ris) { + console.log('ris', ris); + } + } + +}; + +module.exports.getHoursByIdCat = async function (idapp, userId, idCat, date_start, date_end) { + const myfind = [ + { + $match: { + idapp, + userId, + date: { $gte: new Date(date_start), $lte: new Date(date_end) }, + todoId: idCat + } + }, + { + $group: + { + _id: "$todoId", + + totalAmount: { + $sum: "$hours" + }, + count: { + $sum: 1 + } + } + } + ]; + + try { + const ris = await Hours.aggregate(myfind); + if (ris.length > 0) { + return ris[0].totalAmount; + } else { + return 0; + } + } catch (e) { + console.log('e', e); + return 0; + } +}; + +module.exports.getTotalHoursByDate = async function (idapp, userId, date) { + const myfind = [ + { + $match: { + idapp, + userId, + hours: { $gt: 0 }, + date: + { + $gte: new Date(tools.getstrDateYYYY_MM_DD(date)), + $lte: new Date(tools.getstrDateYYYY_MM_DD(tools.AddDate(date, 1))) + } + }, + }, + { + $group: + { + _id: { $dateToString: { format: "%Y-%m-%d", date: "$date" } }, + + totalAmount: { + $sum: "$hours" + }, + count: { + $sum: 1 + } + } + } + ] + ; + + try { + const ris = await Hours.aggregate(myfind); + if (ris.length > 0) { + return ris[0].totalAmount; + } else { + return 0; + } + } catch (e) { + console.log('e', e); + return 0; + } +} +; + +module.exports.getHoursByDate = async function (idapp, userId, date) { + + const mystr = tools.getstrDateYYYY_MM_DD(date); + // console.log(mystr); + const myfind = + { + idapp, + userId, + hours: { $gt: 0 }, + date: { + $gte: new Date(tools.getstrDateYYYY_MM_DD(date)), + $lte: new Date(tools.getstrDateYYYY_MM_DD(tools.AddDate(date, 1))) + } + }; + + try { + return await Hours.find(myfind); + } catch (e) { + console.log('e', e); + return 0; + } +}; + module.exports.calculateHoursTodo = async function (idtodo) { const Hours = this; @@ -93,6 +220,5 @@ module.exports.calculateHoursTodo = async function (idtodo) { return 0; } -} -; +}; diff --git a/src/server/models/project.js b/src/server/models/project.js index 95435b9..7b2b584 100755 --- a/src/server/models/project.js +++ b/src/server/models/project.js @@ -131,6 +131,9 @@ var ProjectSchema = new mongoose.Schema({ privacywrite: { type: String }, + tipovisu: { + type: Number, + }, deleted: { type: Boolean, default: false, @@ -178,6 +181,37 @@ ProjectSchema.statics.findProjectByUserId = function (userId, idproj) { } }; +ProjectSchema.statics.findColorsByProject = async function (idproj) { + const Project = this; + + let finito = false; + + let idparent = idproj; + let colori = {}; + + while (!finito) { + let rec = await Project.findOne({ '_id': idparent }); + + if (!rec) + break; + + if (rec) { + colori.themebgcolor = rec.themebgcolor; + colori.themecolor = rec.themecolor + } + + if (!rec.themebgcolor && !rec.themecolor) { + // Cerca nel progetto ereditato + idparent = rec.id_parent + } else { + break; + } + } + + return colori; + +}; + ProjectSchema.statics.findAllProjByUserId = async function (userId, idapp) { var Project = this; diff --git a/src/server/models/user.js b/src/server/models/user.js index 46d47e7..ec04ea9 100755 --- a/src/server/models/user.js +++ b/src/server/models/user.js @@ -1272,7 +1272,7 @@ UserSchema.statics.getusersManagers = async function (idapp) { UserSchema.statics.getusersRespList = async function (idapp) { const User = this; - return await User.find({ idapp, 'profile.resplist': true }, { _id:1, username: 1, name: 1, surname: 1 }) + return await User.find({ idapp, 'profile.resplist': true }, { _id: 1, username: 1, name: 1, surname: 1 }) .then((arrrec) => { return (!!arrrec) ? arrrec : null; }).catch((e) => { @@ -1283,7 +1283,7 @@ UserSchema.statics.getusersRespList = async function (idapp) { UserSchema.statics.getusersWorkersList = async function (idapp) { const User = this; - return await User.find({ idapp, 'profile.workerslist': true }, { _id:1, username: 1, name: 1, surname: 1 }) + return await User.find({ idapp, 'profile.workerslist': true }, { _id: 1, username: 1, name: 1, surname: 1 }) .then((arrrec) => { return (!!arrrec) ? arrrec : null; }).catch((e) => { @@ -1892,6 +1892,18 @@ UserSchema.statics.getUsersZoom = async function (idapp) { return await User.count(myfind); }; +UserSchema.statics.getUsersResidenti = async function (idapp) { + const User = this; + + const myfind = { + idapp, + $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }], + 'profile.socioresidente': { $exists: true, $eq: true } + }; + + return await User.find(myfind, {username: 1, name: 1, surname: 1}); +}; + UserSchema.statics.getSaw_and_Accepted = async function (idapp) { const User = this; diff --git a/src/server/router/index_router.js b/src/server/router/index_router.js index 66de050..93c535e 100755 --- a/src/server/router/index_router.js +++ b/src/server/router/index_router.js @@ -1109,7 +1109,10 @@ router.get('/loadsite/:userId/:idapp/:sall', authenticate_noerror, (req, res) => let bookedevent = []; // let msgs = []; - const socioresidente = req.user.profile.socioresidente; + let socioresidente = false; + + if (!!req.user) + socioresidente = req.user.profile.socioresidente; if (userId !== '0') { // LOGGED WITH USERID diff --git a/src/server/router/projects_router.js b/src/server/router/projects_router.js index 1f4a9a8..dbccc8b 100755 --- a/src/server/router/projects_router.js +++ b/src/server/router/projects_router.js @@ -47,6 +47,8 @@ router.post('/', authenticate, (req, res) => { .then(record => { // tools.mylog('REC SAVED :', record.descr); + tools.sendNotificationToUser(todo.userId, titolo + ' ' + record.descr, record.descr, '/todo/' + todo.category, '', 'todo', []) + res.send({ record: record._doc }); /* diff --git a/src/server/router/report_router.js b/src/server/router/report_router.js new file mode 100755 index 0000000..c3d5cd8 --- /dev/null +++ b/src/server/router/report_router.js @@ -0,0 +1,144 @@ +const express = require('express'); +const router = express.Router(); + +const tools = require('../tools/general'); + +const server_constants = require('../tools/server_constants'); + +const { authenticate } = require('../middleware/authenticate'); + +// var mongoose = require('mongoose'); + +const { Project } = require('../models/project'); +const { Todo } = require('../models/todo'); +const { User } = require('../models/user'); + +const shared_consts = require('../tools/shared_nodejs'); + +const Hours = require('../models/hours'); + +const _ = require('lodash'); + +const { ObjectID } = require('mongodb'); + +router.post('/load', authenticate, async (req, res) => { + const date_start = req.body.date_start; + const date_end = req.body.date_end; + const filter = req.body.filter; + const idapp = req.body.idapp; + + // tools.mylog('GET REPORT : '); + + // Ottieni la reportistica + // dei progetti + // degli utenti Residenti + // di tutta la settimana + + try { + // Ottieni la lista dei Residenti + const listaResidenti = await User.getUsersResidenti(idapp); + + // Extract all the projects of the userId only + const objprojects = await Project.getAllProjects('', idapp); + + const arrhour = {}; + + let mydatets = tools.dateToEpoch(date_start) + let mydatets_end = tools.dateToEpoch(date_end) + + for (const myuser of listaResidenti) { + arrhour[myuser.username] = []; + } + + let totalacchours = []; + for (const myuser of listaResidenti) { + totalacchours[myuser.username] = 0; + } + + while (mydatets <= mydatets_end) { + for (const myuser of listaResidenti) { + // for (const myproj of objprojects.arrproj) { + //let myhours = await Hours.getHoursByIdCat(idapp, myuser._id, myproj._id, date_start, date_end); + let mydate = new Date(mydatets); + let rechours = await Hours.getHoursByDate(idapp, myuser._id, mydate); + let ressum = await Hours.getTotalHoursByDate(idapp, myuser._id, mydate); + + if (tools.isMonday(mydatets)) { + totalacchours[myuser.username] = 0; + } + + if ((ressum > 0) || ((tools.isSunday(mydatets)) && totalacchours[myuser.username] > 0)) { + totalacchours[myuser.username] = totalacchours[myuser.username] + ressum; + const rectotal = { + totalhours: ressum, + totalacchours: 0, + date: tools.getstrDateYYYY_MM_DD(mydate), + } + + if (tools.isSunday(mydatets)) { + rectotal.totalacchours = totalacchours[myuser.username]; + } + + if (tools.isBitActive(filter, shared_consts.REPORT_FILT_RESP)) { + rectotal.resp = ''; + rectotal.viceResp = ''; + } + + arrhour[myuser.username].push(rectotal); + if (tools.isBitActive(filter, shared_consts.REPORT_FILT_ATTIVITA)) { + for (const rec of rechours) { + let myproj = await Project.findProjectByUserId('', rec.todoId); + let colors = { + themebgcolor: '', + themecolor: '' + } + if (!myproj) { + const mytodo = await Todo.findOne({ _id: rec.todoId }); + if (!!mytodo) { + colors.themebgcolor = mytodo.themebgcolor; + colors.themecolor = mytodo.themecolor; + myproj = await Project.findProjectByUserId('', mytodo.category); + if (!themebgcolor && myproj) { + colors.themebgcolor = myproj.themebgcolor; + colors.themecolor = myproj.themecolor; + } + } + // E' un Todo, trova il proj + } else { + colors.themebgcolor = myproj.themebgcolor; + colors.themecolor = myproj.themecolor; + } + if (!colors.themebgcolor) { + if (myproj) { + colors = await Project.findColorsByProject(myproj._id); + } + } + if (myproj) { + const myrec = { + title: rec.hours + 'h - ' + myproj.descr, + details: myproj.longdescr, + date: tools.getstrDateYYYY_MM_DD(mydate), + bgcolor: colors.themebgcolor, + color: colors.themecolor + } + arrhour[myuser.username].push(myrec); + } + } + } + } + // } + } + mydatets += 86400000; + } + + return res.send({ listaResidenti, arrhour }); + + + } catch (e) { + console.log(e.message); + res.status(400).send(e); + } + +}); + +module.exports = router; diff --git a/src/server/router/todos_router.js b/src/server/router/todos_router.js index a7291e8..cdafcbb 100755 --- a/src/server/router/todos_router.js +++ b/src/server/router/todos_router.js @@ -21,7 +21,7 @@ const _ = require('lodash'); const { ObjectID } = require('mongodb'); -router.post('/', authenticate, (req, res) => { +router.post('/', authenticate, async (req, res) => { var body = _.pick(req.body, tools.allfieldTodoWithId()); // tools.mylogshow('INPUT', body); @@ -48,25 +48,44 @@ router.post('/', authenticate, (req, res) => { console.log('RECORD NON VALIDO !?', req.body) } - todo.save().then((writeresult) => { - let idobj = writeresult._id; - Todo.findById(idobj) - .then(record => { - // tools.mylog('REC SAVED :', record.descr); + let prevrec = null; + if (!!todo && todo._id) + prevrec = await Todo.findById(todo._id); - tools.sendNotificationToUser(todo.userId, 'Todo: ' + record.descr, record.descr, '/todo/' + todo.category, '', 'todo', []) - .then(ris => { - if (ris) { - res.send({ record }); - } else { - // already sent the error on calling sendNotificationToUser + return todo.save() + .then((writeresult) => { + let idobj = writeresult._id; + return Todo.findById(idobj) + .then(record => { + // tools.mylog('REC SAVED :', record.descr); + + let aggiorna = false; + let titolo = ''; + + if (prevrec) { + if (todo.completed_at !== prevrec.completed_at) { + aggiorna = true; + titolo = 'Attività Completata!' } - }) - }) - }).catch((e) => { - console.log('ERRORE in TODO POST', e.message); - res.status(400).send(e); - }); + } else { + aggiorna = true; + } + + if (aggiorna) { + tools.sendNotificationToUser(todo.userId, titolo + ' ' + record.descr, record.descr, '/todo/' + todo.category, '', 'todo', []) + .then(ris => { + if (ris) { + return res.send({ record }); + } else { + // already sent the error on calling sendNotificationToUser + } + }) + } + }) + }).catch((e) => { + console.log('ERRORE in TODO POST', e.message); + return res.status(400).send(e); + }); }); @@ -101,7 +120,7 @@ router.patch('/:id', authenticate, (req, res) => { .then(objdatacalc => { // tools.mylogshow(' TODO TO MODIFY: ', todo.descr, todo.expiring_at); - if (todo.userId !== String(req.user._id) && project.privacywrite === server_constants.Privacy.onlyme) { + if (todo.userId !== String(req.user._id) && todo.privacywrite === server_constants.Privacy.onlyme) { // I'm trying to write something not mine! return res.status(404).send({ code: server_constants.RIS_CODE_TODO_CREATING_NOTMYUSER }); } diff --git a/src/server/router/users_router.js b/src/server/router/users_router.js index 408ffc4..d3ca79f 100755 --- a/src/server/router/users_router.js +++ b/src/server/router/users_router.js @@ -4,6 +4,7 @@ const router = express.Router(); const { User } = require('../models/user'); const { Nave } = require('../models/nave'); const { Flotta } = require('../models/flotta'); +const Hours = require('../models/hours'); const { NavePersistente } = require('../models/navepersistente'); const { ListaIngresso } = require('../models/listaingresso'); const { Graduatoria } = require('../models/graduatoria'); @@ -752,6 +753,10 @@ async function eseguiDbOp(idapp, mydata, locale) { telegrambot.sendMsgTelegramToTheAdmin(idapp, placca); ris = { placca };*/ + } else if (mydata.dbop === 'CorreggiTabHours') { + + await Hours.correggiHours(idapp); + } else if (mydata.dbop === 'visuNave') { mystr = await Nave.getNavePos(idapp, parseInt(mydata.riga), parseInt(mydata.col)); diff --git a/src/server/server.js b/src/server/server.js index 1d9918b..31bbd1c 100755 --- a/src/server/server.js +++ b/src/server/server.js @@ -58,6 +58,7 @@ const email_router = require('./router/email_router'); const todos_router = require('./router/todos_router'); const test_router = require('./router/test_router'); const projects_router = require('./router/projects_router'); +const report_router = require('./router/report_router'); const users_router = require('./router/users_router'); const site_router = require('./router/site_router'); const admin_router = require('./router/admin_router'); @@ -129,6 +130,7 @@ app.use('/todos', todos_router); app.use('/test', test_router); app.use('/projects', projects_router); app.use('/users', users_router); +app.use('/report', report_router); app.use('/site', site_router); app.use('/admin', admin_router); app.use('/products', products_router); diff --git a/src/server/telegram/telegrambot.js b/src/server/telegram/telegrambot.js index 52812a1..1f163a4 100755 --- a/src/server/telegram/telegrambot.js +++ b/src/server/telegram/telegrambot.js @@ -1,9 +1,9 @@ const tools = require('../tools/general'); -const appTelegram = [tools.AYNI, tools.SIP]; +const appTelegram = [tools.CNM]; const appTelegramFinti = ['2']; -const appTelegramDest = [tools.AYNI]; +const appTelegramDest = [tools.CNM]; const printf = require('util').format; diff --git a/src/server/tools/general.js b/src/server/tools/general.js index 4882745..20ab416 100755 --- a/src/server/tools/general.js +++ b/src/server/tools/general.js @@ -483,7 +483,7 @@ module.exports = { LANGADMIN: 'it', AYNI: '7', - SIP: '9', + CNM: '10', HELP_CHAT: 'https://t.me/joinchat/AL2qKE80rxDkgbeMGO-0bw', TYPECONF_ZOOM: 'zoom', @@ -633,7 +633,7 @@ module.exports = { allfieldProject: function () { return ['idapp', 'userId', 'respUsername', 'viceRespUsername', 'pos', 'typeproj', 'id_main_project', 'id_parent', 'descr', 'longdescr', 'groupId', 'hoursplanned', 'hoursleft', 'themecolor', 'themebgcolor', 'hoursworked', 'priority', 'statusproj', 'created_at', 'modify_at', 'completed_at', 'expiring_at', 'enableExpiring', 'progressCalc', 'modified', 'live_url', 'test_url', 'begin_development', 'begin_test', 'totalphases', 'actualphase', 'hoursweeky_plannedtowork', 'endwork_estimate' - , 'privacyread', 'privacywrite'] + , 'privacyread', 'privacywrite', 'tipovisu'] }, allfieldBooking: function () { @@ -1074,7 +1074,7 @@ module.exports = { filtriadded.push( { idapp, - userId: ObjectID(params.userId), + userId: params.userId, todoId: params.codeId, $or: [{ deleted: { $exists: false } }, { deleted: { $exists: true, $eq: false } }] } @@ -1157,26 +1157,18 @@ module.exports = { }, - executeQueryTable(mythistable, idapp, params) { + async executeQueryTable(mythistable, idapp, params) { let query = this.getQueryTable(idapp, params); - return mythistable - .aggregate(query) - .then(([ris]) => { - if (ris) { - // console.table(ris.rows); - // console.log('ROW ', ris.count); - return ({ count: ris.count, rows: ris.rows }) - } else { - return ({ count: 0, rows: [] }) - } - }) - .catch(err => { - console.error(err); - return { - count: 0, rows: [] - } - }); + const [ris] = await mythistable.aggregate(query); + + if (ris) { + // console.table(ris.rows); + // console.log('ROW ', ris.count); + return ({ count: ris.count, rows: ris.rows }) + } else { + return ({ count: 0, rows: [] }) + } }, async DuplicateAllRecords(mythistable, idapporig, idappdest) { @@ -1369,6 +1361,16 @@ module.exports = { } }, + isSunday(mydate) { + const dayOfWeek = new Date(mydate).getDay() + return dayOfWeek === 0 + }, + + isMonday(mydate) { + const dayOfWeek = new Date(mydate).getDay() + return dayOfWeek === 1 + }, + getWeekDayByLang(date, lang) { return this.getWeekDayByLangByNumCar(date, lang, 3) }, @@ -1406,6 +1408,15 @@ module.exports = { } }, + getstrDateYYYY_MM_DD(mydate) { + if (mydate) { + // console.log('getstrDate', mytimestamp) + return mydate.getFullYear() + '-' + this.appendLeadingZeroes(mydate.getMonth() + 1) + '-' + this.appendLeadingZeroes(mydate.getDate()) + } else { + return ''; + } + }, + getstrDateLong(mydate, lang) { if (mydate) { // console.log('getstrDate', mytimestamp) @@ -1886,4 +1897,14 @@ module.exports = { return { query, order } }, + dateToEpoch(thedate) { + const time = new Date(thedate).getTime(); + return time - (time % 86400000); + }, + + dateToEpochStr(thedate) { + const time = new Date(thedate).getTime(); + return new Date(time - (time % 86400000)); + } + }; diff --git a/src/server/tools/shared_nodejs.js b/src/server/tools/shared_nodejs.js index fbe7a4b..b9ef35b 100755 --- a/src/server/tools/shared_nodejs.js +++ b/src/server/tools/shared_nodejs.js @@ -26,6 +26,9 @@ module.exports = { FILTER_HOURS_MYLIST: 65536, FILTER_HOURS_ALL: 131072, + REPORT_FILT_RESP: 1, + REPORT_FILT_ATTIVITA: 2, + Permissions: { Admin: 1, Manager: 2,