Files
freeplanet_serverside/server/models/todo.js
2019-04-25 00:30:19 +02:00

453 lines
10 KiB
JavaScript

var mongoose = require('mongoose');
const _ = require('lodash');
const tools = require('../tools/general');
var { Project } = require('./project');
var server_constants = require('../tools/server_constants');
mongoose.Promise = global.Promise;
mongoose.level = "F";
// Resolving error Unknown modifier: $pushAll
mongoose.plugin(schema => {
schema.options.usePushEach = true
});
mongoose.set('debug', process.env.DEBUG);
var TodoSchema = new mongoose.Schema({
userId: {
type: String,
},
pos: {
type: Number,
},
category: mongoose.Schema.Types.ObjectId,
descr: {
type: String,
},
priority: {
type: Number,
},
statustodo: {
type: Number,
default: 0
},
created_at: {
type: Date
},
modify_at: {
type: Date
},
start_date: {
type: Date,
},
completed_at: {
type: Date
},
expiring_at: {
type: Date,
},
enableExpiring: {
type: Boolean,
default: false
},
id_prev: mongoose.Schema.Types.ObjectId,
progress: {
type: Number,
},
phase: {
type: Number,
},
assigned_to_userId: {
type: String,
},
hoursplanned: {
type: Number,
},
hoursworked: {
type: Number,
},
modified: {
type: Boolean,
},
});
TodoSchema.methods.toJSON = function () {
var todo = this;
var todoObject = todo.toObject();
// console.log(todoObject);
return _.pick(todoObject, tools.allfieldTodoWithId());
};
TodoSchema.statics.findByUserIdAndIdParent = function (userId, category, phase = '') {
var Todo = this;
let tofind = {
'category': category,
};
if (userId !== '') {
tofind['userId'] = userId;
}
if (!!phase) {
tofind['phase'] = phase;
}
return Todo.find(tofind);
};
// User.find({ admin: true }).where('created_at').gt(monthAgo).exec(function(err, users) {
// if (err) throw err;
function getQueryFilterTodo(userId) {
myobj = [{ privacyread: server_constants.Privacy.all }, { userId: userId }];
return myobj;
}
function getQueryTodo(filterMatchBefore = {}, userId) {
let filterMatchAfter = {
$or: getQueryFilterTodo(userId)
};
let myobjField = getobjFieldTodo(true);
const query = [
{ $match: filterMatchBefore },
{
$lookup: {
from: "projects",
localField: "category", // field in the Todo collection
foreignField: "_id", // field in the projects collection
as: "fromItems"
}
},
{
$replaceRoot: { newRoot: { $mergeObjects: [{ $arrayElemAt: ["$fromItems", 0] }, "$$ROOT"] } }
},
{ $match: filterMatchAfter },
{ $project: myobjField }];
return query;
}
TodoSchema.statics.findAllByUserIdAndCat = function (userId) {
var Todo = this;
const query = getQueryTodo({}, userId);
return Todo.aggregate(query)
.then(ris => {
// console.log('ris TODO:', ris);
//return tools.mapSort(ris)
return ris
});
};
TodoSchema.statics.getArrIdParentInTable = function (userId) {
var Todo = this;
return Todo.find(getQueryFilterTodo(userId)).distinct("category")
.then(arrcategory => {
return arrcategory
})
};
function getobjFieldTodo(withprojectfield) {
let objfield = {};
for (const field of tools.allfieldTodo()) {
objfield[field] = 1;
}
if (withprojectfield) {
objfield["privacyread"] = 1;
objfield["privacywrite"] = 1;
}
// console.log("getobjFieldTodo", objfield);
return objfield
}
TodoSchema.statics.enabletoModify = async function (userId, idTodo) {
var Todo = this;
let params = {};
params['_id'] = ObjectId(idTodo);
const query = getQueryTodo(params, userId);
return Todo.aggregate(query)
.then(ris => {
return (!!ris);
})
.catch(err => {
console.log("ERR: ".err);
return false;
});
};
TodoSchema.statics.getAllTodo = async function (userId) {
var Todo = this;
const arralltodo = await Todo.findAllByUserIdAndCat(userId);
// console.log('arralltodo', arralltodo);
let obj = [];
obj.arrcategories = await Todo.getArrIdParentInTable(userId);
// console.log('obj.arrcategories', obj.arrcategories);
let arrtodos = [];
if (obj.arrcategories.length > 0) {
for (const mycat of obj.arrcategories) {
if (!!arralltodo) {
const arrfiltrato = arralltodo.filter(item => item.category.toString() === mycat.toString());
if (arrfiltrato.length > 0) {
const arrmap = tools.mapSort(arrfiltrato);
arrtodos.push(arrmap);
// console.log('AGGIUNGI RECORDS TODO! cat: ', mycat, 'da aggiungere:', arrfiltrato.length, 'attuali', arrtodos.length);
// console.log(arrtodos)
} else {
arrtodos.push([]);
}
}
}
}
obj.arrtodos = arrtodos;
// console.log('obj.arrtodos:');
// logtodo(obj.arrtodos);
return obj;
};
function getelem(item) {
return item.descr + ' ' + item.category;
}
function logtodo(myarr) {
console.log(getarrlog(myarr));
}
function getarrlog(myarr) {
let mystr = "";
for (const indcat in myarr) {
mystr += indcat + ': \n';
for (const indelem in myarr[indcat]) {
mystr += ' [' + indelem + '] ' + getelem(myarr[indcat][indelem]) + '\n';
}
}
return mystr
}
class CalcTodo {
constructor(phase) {
this.mydata = {
phase: phase,
numitem: 0
};
this.clean()
}
clean() {
this.mydata.hoursplanned = 0;
this.mydata.hoursworked = 0;
this.mydata.progressCalc = 0;
}
addDataProj(datain) {
if (!!datain) {
if (datain.actualphase === this.mydata.phase) {
CalcTodo.addFields(this.mydata, datain, true);
}
}
}
addDataTodo(datain) {
if (!!datain) {
if (datain.phase === this.mydata.phase) {
CalcTodo.addFields(this.mydata, datain, false);
}
}
}
static addFields(recout, recin, isproj) {
// console.log('addFields', recin);
recout.hoursworked += recin.hoursworked;
recout.hoursplanned += recin.hoursplanned;
if (recin.progress === undefined) {
recout.progressCalc += recin.progressCalc;
} else {
recout.progressCalc += recin.progress;
}
recout.numitem++;
}
static copyFields(recout, recin) {
recout.hoursworked = recin.hoursworked;
recout.hoursplanned = recin.hoursplanned;
if (recin.progress === undefined)
recout.progressCalc = recin.progressCalc;
else {
if (!!recin.progressCalc)
recout.progressCalc = recin.progressCalc;
else
recout.progressCalc = 0;
}
}
setValuesToRecord(objout) {
CalcTodo.copyFields(objout, this.mydata)
}
endDataCalc() {
if (this.mydata.numitem > 0) {
this.mydata.progressCalc = Math.round(this.mydata.progressCalc / this.mydata.numitem);
}
console.log('this.mydata.progressCalc', this.mydata.progressCalc)
}
getData() {
// return tools.jsonCopy(this.mydata);
return { ...this.mydata }
}
}
TodoSchema.statics.calculateTreeTodo = async function (actualphase, userId, idproj, calcalsoUpper, masterproj, nocalcDown) {
// console.log('calculateTreeTodo', 'actualphase', actualphase, idproj);
const myrecproj = await Project.findProjectByUserId(userId, idproj);
// const id_parent = await Project.getIdParentByIdProj(idproj);
let objdata = new CalcTodo(actualphase);
let promiseChain = Promise.resolve();
return await Project.findByUserIdAndIdParent(userId, idproj)
.then(arrsubproj => {
// console.log(' ', arrsubproj.length, 'SubProjects trovati');
// console.log('arrsubproj', 'userId', userId, 'idproj', idproj, arrsubproj.length);
if (!nocalcDown) {
// 1) Calculate the SubProjects of this project Main
for (const subproj of arrsubproj) {
if (!calcalsoUpper) { // not include the first Project because it was already calculated before
promiseChain = promiseChain.then(() => {
return Todo.calculateTreeTodo(actualphase, userId, subproj._id, calcalsoUpper, masterproj, true)
.then((subobjdata) => {
objdata.addDataProj(subobjdata);
});
});
} else {
promiseChain = promiseChain.then(() => {
objdata.addDataProj(subproj);
});
}
}
}
return promiseChain;
})
.then(() => {
// console.log('objdata', objdata);
// 2) Calculate the Todos of this project
return Todo.calculateTodoHoursAndProgress(userId, idproj, myrecproj.actualphase);
})
.then((objdatatodos) => {
if (myrecproj.actualphase === actualphase) {
// console.log('objdatatodos', objdatatodos);
objdata.addDataTodo(objdatatodos);
// End Calculate
objdata.endDataCalc();
// Update into the DB:
return Project.updateCalc(userId, idproj, objdata, null)
.then((ris) => {
if (ris)
return objdata.getData();
else
return null;
});
} else {
return null;
}
})
.then((ris) => {
if (calcalsoUpper) {
if (!!myrecproj.id_parent) {
// Calculate also the upper Projects !
return new Promise((resolve, reject) => {
Todo.calculateTreeTodo(actualphase, userId, myrecproj.id_parent, true, masterproj, false);
resolve(ris)
});
} else {
return new Promise((resolve, reject) => {
resolve()
});
}
} else {
return new Promise((resolve, reject) => {
resolve()
});
}
})
};
TodoSchema.statics.calculateTodoHoursAndProgress = async function (userId, idproj, actualphase) {
var Todo = this;
let objdata = new CalcTodo(actualphase);
return await Todo.findByUserIdAndIdParent(userId, idproj, actualphase)
.then(arrtodo => {
// console.log(' calculateTodo *', arrtodo.length, '* FOUND');
for (let itemtodo of arrtodo) {
objdata.addDataTodo(itemtodo);
}
objdata.endDataCalc();
return objdata.getData();
})
.catch(e => {
console.log('Error: ', e);
return null;
});
};
TodoSchema.pre('save', function (next) {
// var todo = this;
// console.log('todo.expiring_at', todo.expiring_at);
next();
});
var Todo = mongoose.model('Todos', TodoSchema);
module.exports = { Todo };