<commit_before>'use strict';
var mongoose = require('mongoose');
var ReservationsSchema = require('./mongo-schema.js');
var error = require('../../helpers/error.js');
var Rooms = require('../rooms/class.js');

ReservationsSchema.statics.findAllInRange = function (checkIn, checkOut, cb) {
  this.find({
    checkIn: {
      $lt: checkOut
    },
    checkOut: {
      $gt: checkIn
    }
  }, cb);
};

ReservationsSchema.statics.findAllWithRoomIds = function (roomIds, cb) {
  this.find({
    rooms: {
      $elemMatch: {
        $in: roomIds
      }
    }
  }, {
    rooms: 1,
    timeLastEdit: 1
  },
  {
    checkIn: 1 // sort by accending out[0] = smallest number (oldest)
  }, cb);
};

ReservationsSchema.methods.makeReservation = function (cb) {
  var self = this;
  self.save(function(err, newReservation) {
    if (err) { return cb(err); }
    self.ensureRoomAvalibility(function(err) {
      cb(err, newReservation);
    });
  });
};

ReservationsSchema.methods.ensureRoomAvalibility = function (cb) {
  var self = this;
  // if rooms, ensure it is avalible
  if (self.rooms.length > 0) {
    Reservations.findAllWithRoomIds(self.rooms, function(err, reservations) {
      if (err) { return cb(err); }
      // if we are oldest reservation no need to revert (must be sorted accending)
      if (self._id.equals(reservations[0]._id)) { return cb(); }
      // we need to revert
      handleConflict('room already reserved', reservations);
    });
  } else { // just do count of rooms
    Reservations.findAllInRange(self.checkIn, self.checkOut, function(err, reservations) {
      if (err) { return cb(err); }
      Rooms.find({}, function(err, rooms) {
        if (err) { return cb(err); }
        // valid if we have more rooms then reservations
        if (rooms.length >= reservations.length) { return cb(); }
        // no room left, revert
        handleConflict('no more rooms avalible', reservations);
      });
    });
  }

  function handleConflict(message, data) {
    self.remove(function(err) {
      error.logIfError(err);
      cb(error.Boom.conflict(message, data));
    });
  }
};


var Reservations = module.exports = mongoose.model('Reservations', ReservationsSchema);<commit_msg>add checks for room and guest existance<commit_after>'use strict';
var mongoose = require('mongoose');
var ReservationsSchema = require('./mongo-schema.js');
var error = require('../../helpers/error.js');
var Rooms = require('../rooms/class.js');
var Guests = require('../guests/class.js');

ReservationsSchema.statics.findAllInRange = function (checkIn, checkOut, cb) {
  this.find({
    checkIn: {
      $lt: checkOut
    },
    checkOut: {
      $gt: checkIn
    }
  }, cb);
};

ReservationsSchema.statics.findAllWithRoomIds = function (roomIds, cb) {
  this.find({
    rooms: {
      $elemMatch: {
        $in: roomIds
      }
    }
  }, {
    rooms: 1,
    timeLastEdit: 1
  },
  {
    checkIn: 1 // sort by accending out[0] = smallest number (oldest)
  }, cb);
};

ReservationsSchema.methods.makeReservation = function (cb) {
  var self = this;
  self.save(function(err, newReservation) {
    if (err) { return cb(err); }
    self.validateReservation(function(err) {
      // if error, revert
      if (err) {
        return self.remove(function(removeErr) {
          error.logIfError(removeErr);
          cb(err);
        });
      }
      cb(null, newReservation);
    });
  });
};

ReservationsSchema.methods.validateReservation = function (cb) {
  var self = this;
  // ensure guest exists
  Guests.ensureGuestsExists(self.guests, function(err) {
    if (err) { return cb(err); }
    // if rooms, ensure it is avalible
    if (self.rooms.length > 0) {
      ensureRoomsNotTaken(self.rooms, self._id, cb);
    } else { // just do count of rooms
      ensureEmptyRoomsExists(self.checkIn, self.checkOut, cb);
    }
  });
};

function ensureRoomsNotTaken(rooms, id, cb) {
  Rooms.ensureRoomsExists(rooms, function(err){
    if (err) { return cb(err); }
    Reservations.findAllWithRoomIds(rooms, function(err, reservations) {
      if (err) { return cb(err); }
      // if we are oldest reservation no need to revert (must b'e sorted accending)
      if (id.equals(reservations[0]._id)) { return cb(); }

      cb(error.Boom.conflict('room already reserved', reservations));
    });
  });
}

function ensureEmptyRoomsExists(checkIn, checkOut, cb) {
  Reservations.findAllInRange(checkIn, checkOut, function(err, reservations) {
    if (err) { return cb(err); }
    Rooms.find({}, function(err, rooms) {
      if (err) { return cb(err); }
      // valid if we have more rooms then reservations
      if (rooms.length >= reservations.length) { return cb(); }
      // no room left
      cb(error.Boom.conflict('no more rooms avalible', reservations));
    });
  });
}

var Reservations = module.exports = mongoose.model('Reservations', ReservationsSchema);
{'fraction_non_alphanumeric': 0.14564502875924404, 'fraction_numerical': 0.0024650780608052587, 'mean_word_length': 3.0239669421487605, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, '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': '2114415', 'n_tokens_mistral': 1599, 'n_tokens_neox': 1569, 'n_words': 368}