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

var Objectid = mongoose.Schema.Types.ObjectId;
var Room = require("./room_model");
var User = require("./user_model");
var Guest = require("./guest_model");
var Reserve = require("./reserve_model");
var Ledger = require("./ledger_model");
var Layout = require("./layout_model");
var moment = require('moment-timezone');

moment.tz.setDefault("SAST");

var BookingSchema   = new Schema({
	room: { type: Objectid, ref: "Room" },
	start_time: Date,
	end_time: Date,
	title: String,
	description: String,
	message: String,
	attendees: [{ type: Objectid, ref: "User" }],
	guests: [{ type: Objectid, ref: "Guest" }],
	external_attendees: [String],
	user: { type: Objectid, ref: "User" },
	cost: Number,
	created: { type: Date, default: Date.now },
	public_event: { type: Boolean, default: false },
	event_client: { type: Boolean, default: false },
	img: String,
	layout: { type: Objectid, ref: "Layout" },
	booking_url: String,
	website: String,
	_owner_id: Objectid,
	_deleted: { type: Boolean, default: false, index: true },
	_version: { type: Number, default: 0 },
});

BookingSchema.set("_perms", {
	admin: "crud",
	owner: "crud",
	user: "cr",
});

function collision_detection(appointment, appointments) {
	console.log("Checking for collision");
	if (!appointments) {
		return false;
	}
	var appointment_index = appointments.indexOf(appointment);
	for(var x = 0; x < appointments.length; x++) {
		if (x != appointment_index) {
			if (appointment.start_time < appointments[x].end_time && appointments[x].start_time < appointment.end_time) {
				console.log("Collision", appointments[x].start_time, appointments[x].end_time);
				console.log("Appointment", appointment.start_time, appointment.end_time);
				return true;
			}
		}
	}
	return false;
}

BookingSchema.pre("save", function(next) {
	var transaction = this;
	var Booking = mongoose.model("Booking", BookingSchema);
	Booking.find({ end_time: { $gt: transaction.start_time }, start_time: { $lt: transaction.end_time }, room: transaction.room }, function(err, result) {
		console.log("Checking that this slot is available", result);
		if (result.length && ("" + transaction._id !== "" + result[0]._id) && (!transaction._deleted)) {
			console.error("Booking clash", result[0]._id, transaction._id);
			throw({ message: "This booking clashes with an existing booking" });
		}
		try {
			//Remove the reserve if it already exists
			Ledger.findOne({
				source_type: "booking",
				source_id: transaction._id
			}, function(err, item) {
				if (item) {
					console.log("Found existing transaction");
					item.remove();
				}
			});
		} catch(err) {
			console.log("Error", err);
			// throw(err);<commit_msg>Ignore deleted bookings when looking for clashes<commit_after>var mongoose     = require('mongoose');
var Schema       = mongoose.Schema;

var Objectid = mongoose.Schema.Types.ObjectId;
var Room = require("./room_model");
var User = require("./user_model");
var Guest = require("./guest_model");
var Reserve = require("./reserve_model");
var Ledger = require("./ledger_model");
var Layout = require("./layout_model");
var moment = require('moment-timezone');

moment.tz.setDefault("SAST");

var BookingSchema   = new Schema({
	room: { type: Objectid, ref: "Room" },
	start_time: Date,
	end_time: Date,
	title: String,
	description: String,
	message: String,
	attendees: [{ type: Objectid, ref: "User" }],
	guests: [{ type: Objectid, ref: "Guest" }],
	external_attendees: [String],
	user: { type: Objectid, ref: "User" },
	cost: Number,
	created: { type: Date, default: Date.now },
	public_event: { type: Boolean, default: false },
	event_client: { type: Boolean, default: false },
	img: String,
	layout: { type: Objectid, ref: "Layout" },
	booking_url: String,
	website: String,
	_owner_id: Objectid,
	_deleted: { type: Boolean, default: false, index: true },
	_version: { type: Number, default: 0 },
});

BookingSchema.set("_perms", {
	admin: "crud",
	owner: "crud",
	user: "cr",
});

function collision_detection(appointment, appointments) {
	console.log("Checking for collision");
	if (!appointments) {
		return false;
	}
	var appointment_index = appointments.indexOf(appointment);
	for(var x = 0; x < appointments.length; x++) {
		if (x != appointment_index) {
			if (appointment.start_time < appointments[x].end_time && appointments[x].start_time < appointment.end_time) {
				console.log("Collision", appointments[x].start_time, appointments[x].end_time);
				console.log("Appointment", appointment.start_time, appointment.end_time);
				return true;
			}
		}
	}
	return false;
}

BookingSchema.pre("save", function(next) {
	var transaction = this;
	var Booking = mongoose.model("Booking", BookingSchema);
	Booking.find({ end_time: { $gt: transaction.start_time }, start_time: { $lt: transaction.end_time }, room: transaction.room, _deleted: false }, function(err, result) {
		console.log("Checking that this slot is available", result);
		if (result.length && ("" + transaction._id !== "" + result[0]._id) && (!transaction._deleted)) {
			console.error("Booking clash", result[0]._id, transaction._id);
			throw({ message: "This booking clashes with an existing booking" });
		}
		try {
			//Remove the reserve if it already exists
			Ledger.findOne({
				source_type: "booking",
				source_id: transaction._id
			}, function(err, item) {
				if (item) {
					console.log("Found existing transaction");
					item.remove();
				}
			});
		} catch(err) {
			console.log("Error", err);
			// throw(err);
{'fraction_non_alphanumeric': 0.16109313196691838, 'fraction_numerical': 0.001438331535418914, 'mean_word_length': 4.579739217652959, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 3, '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': '2937205', 'n_tokens_mistral': 1954, 'n_tokens_neox': 1823, 'n_words': 453}