<commit_before>var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var ObjectId = mongoose.Schema.Types.ObjectId;
var Mixed = mongoose.Schema.Types.Mixed;
var Opportunity = require("./opportunity_model");
var User = require("./user_model");
var Track = require("./track_model");
var Task = require("./task_model");
var Location = require('./location_model');
var moment = require("moment");

var TaskSchema   = new Schema({
	name: String,
	category: { type: String, validate: /init|call|email|follow_up|meeting|milestone|site_visit/, index: true, default: "email", required: true },
	due_after_task: { type: ObjectId, ref: "Task" },
	due_after_days: Number,
	absolute_due_date: Date,
	original_due_date: Date,
	user_id: { type: ObjectId, ref: "User", index: true, required: true },
	opportunity_id: { type: ObjectId, ref: "Opportunity", index: true, required: true },
	location_id: { type: ObjectId, index: true, ref: "Location" },
	track_id: { type: ObjectId, ref: "Track", index: true },
	template_task_id: ObjectId,
	date_completed: Date,
	completed: { type: Boolean, default: false, index: true },
	abandoned: { type: Boolean, default: false, index: true },
	notes: [{ 
		note: String, 
		date_created: { type: Date, default: Date.now }, 
		user_id: { type: ObjectId, ref: "User" } 
	}],
	data: { type: Mixed },
	date_created: { type: Date, default: Date.now },
	due_date: { type: Date },
	_owner_id: ObjectId
});

TaskSchema.set("_perms", {
	admin: "crud",
});

var findDueDate = task => {
	// console.log({ task });
	if (!task)
		return Promise.resolve();
	if (task.category === "init")
		return Promise.resolve(task.date_created);
	if (task.absolute_due_date)
		return Promise.resolve(task.absolute_due_date);
	if (!task.due_after_task)
		return Promise.resolve(task.date_created);
	if (task.completed)
			return Promise.resolve(task.date_completed);
	let Task = require("./task_model");
	return Task.findOne({ _id: task.due_after_task })
	.then(due_after_task => {
		return moment(due_after_task.due_date).add(task.due_after_days || 0, "days");
	})
};

TaskSchema.pre("save", function(next) {
	var self = this;
	let Task = require("./task_model");
	findDueDate(self)
	.then(result => {
		self.due_date = result;
		return Task.find({ due_after_task: self._id });
	})
	.then(result => {
		if (result)
			result.forEach(item => item.save());
		if (self.isNew)
			self.original_due_date = self.due_date;
		return next();
	})
	.catch(err => {
		console.trace(err);
		return next(err);
	});
})

module.exports = mongoose.model('Task', TaskSchema);<commit_msg>Date completed and touch all future tasks<commit_after>var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var ObjectId = mongoose.Schema.Types.ObjectId;
var Mixed = mongoose.Schema.Types.Mixed;
var Opportunity = require("./opportunity_model");
var User = require("./user_model");
var Track = require("./track_model");
var Task = require("./task_model");
var Location = require('./location_model');
var moment = require("moment");

var TaskSchema   = new Schema({
	name: String,
	category: { type: String, validate: /init|call|email|follow_up|meeting|milestone|site_visit/, index: true, default: "email", required: true },
	due_after_task: { type: ObjectId, ref: "Task" },
	due_after_days: Number,
	absolute_due_date: Date,
	original_due_date: Date,
	user_id: { type: ObjectId, ref: "User", index: true, required: true },
	opportunity_id: { type: ObjectId, ref: "Opportunity", index: true, required: true },
	location_id: { type: ObjectId, index: true, ref: "Location" },
	track_id: { type: ObjectId, ref: "Track", index: true },
	template_task_id: ObjectId,
	date_completed: Date,
	completed: { type: Boolean, default: false, index: true },
	abandoned: { type: Boolean, default: false, index: true },
	notes: [{ 
		note: String, 
		date_created: { type: Date, default: Date.now }, 
		user_id: { type: ObjectId, ref: "User" } 
	}],
	data: { type: Mixed },
	date_created: { type: Date, default: Date.now },
	due_date: { type: Date },
	_owner_id: ObjectId
});

TaskSchema.set("_perms", {
	admin: "crud",
});

var findDueDate = task => {
	// console.log({ task });
	if (!task)
		return Promise.resolve();
	if (task.category === "init")
		return Promise.resolve(task.date_created);
	if (task.absolute_due_date)
		return Promise.resolve(task.absolute_due_date);
	if (!task.due_after_task)
		return Promise.resolve(task.date_created);
	if (task.completed)
			return Promise.resolve(task.date_completed);
	let Task = require("./task_model");
	return Task.findOne({ _id: task.due_after_task })
	.then(due_after_task => {
		return moment(due_after_task.due_date).add(task.due_after_days || 0, "days");
	})
};

// Due Date calculations
TaskSchema.pre("save", function(next) {
	var self = this;
	let Task = require("./task_model");
	findDueDate(self)
	.then(result => {
		self.due_date = result;
		return Task.find({ due_after_task: self._id });
	})
	.then(result => {
		if (result)
			result.forEach(item => item.save());
		if (self.isNew)
			self.original_due_date = self.due_date;
		return next();
	})
	.catch(err => {
		console.trace(err);
		return next(err);
	});
});

// Set Completed Date
TaskSchema.pre("save", function(next) {
	var self = this;
	if (self.isNew)
		return;
	if (self.completed && !self.date_completed)
		self.date_completed = new Date();
	next();
});

// Touch all tasks that rely on this task's due date
TaskSchema.post("save", function(doc) {
	let Task = require("./task_model");
	Task.find({ due_after_task: doc._id })
	.then(result => {
		result.forEach(item => {
			item.save();
		})
	});
});

module.exports = mongoose.model('Task', TaskSchema);
{'fraction_non_alphanumeric': 0.1651101321585903, 'fraction_numerical': 0.0003524229074889868, 'mean_word_length': 4.69307923771314, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1162091', 'n_tokens_mistral': 2040, 'n_tokens_neox': 1963, 'n_words': 465}