- Create Newsletter Page: MailingList (without the class style, using Gulp tasks)#94
This commit is contained in:
473
src/server/models/todo.js
Normal file
473
src/server/models/todo.js
Normal file
@@ -0,0 +1,473 @@
|
||||
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,
|
||||
},
|
||||
themecolor: {
|
||||
type: String,
|
||||
},
|
||||
themebgcolor: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
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.hoursleft = 0;
|
||||
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;
|
||||
let hoursleft = (recin.hoursplanned - recin.hoursworked);
|
||||
if (hoursleft < 0)
|
||||
hoursleft = 0;
|
||||
recout.hoursleft += hoursleft;
|
||||
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;
|
||||
recout.hoursleft = recin.hoursleft;
|
||||
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
|
||||
if (!!myrecproj)
|
||||
return Todo.calculateTodoHoursAndProgress(userId, idproj, myrecproj.actualphase);
|
||||
else
|
||||
return null
|
||||
})
|
||||
.then((objdatatodos) => {
|
||||
|
||||
if (!!objdatatodos) {
|
||||
if (!!myrecproj) {
|
||||
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;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
})
|
||||
.then((ris) => {
|
||||
if (calcalsoUpper) {
|
||||
if (!!myrecproj) {
|
||||
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()
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 };
|
||||
|
||||
Reference in New Issue
Block a user