[WIP] Multi-Calendar

This commit is contained in:
QS5ELkMu
2018-12-08 22:15:37 +01:00
parent 6d93e850cb
commit ec211d6c5b
6 changed files with 759 additions and 717 deletions

View File

@@ -64,8 +64,8 @@ class BusHotelCalendar(models.TransientModel):
vals['checkin'],
num_split,
vals['price'],
vals['reservation_type'],
vals['out_service_description'],
vals['reservation_type'] if 'reservation_type' in vals else 'normal',
vals['out_service_description'] if 'out_service_description' in vals else '',
]
}

View File

@@ -416,6 +416,7 @@ class HotelReservation(models.Model):
@api.multi
def write(self, vals):
ret = super(HotelReservation, self).write(vals)
_logger.info("RESERV WRITE")
if 'partner_id' in vals or 'checkin' in vals or \
'checkout' in vals or 'product_id' in vals or \
'adults' in vals or 'children' in vals or \
@@ -425,7 +426,9 @@ class HotelReservation(models.Model):
'reserve_color' in vals or \
'reserve_color_text' in vals or 'product_id' in vals or \
'parent_reservation' in vals or 'overbooking' in vals:
_logger.info("PASA RESERV WRITE")
for record in self:
_logger.info("PASA RESERV WRITE 22")
record.send_bus_notification(
'write',
(record.state == 'cancelled') and 'warn' or 'notify',

View File

@@ -51,18 +51,6 @@ var HotelCalendarView = AbstractRenderer.extend({
},
/** CUSTOM METHODS **/
_generate_reservation_tooltip_dict: function(tp) {
return {
'name': tp[0],
'phone': tp[1],
'arrival_hour': HotelCalendar.toMomentUTC(tp[2], HotelConstants.ODOO_DATETIME_MOMENT_FORMAT).local().format('HH:mm'),
'num_split': tp[3],
'amount_total': Number(tp[4]).toLocaleString(),
'reservation_type': tp[5],
'out_service_description': tp[6]
};
},
get_view_filter_dates: function () {
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
@@ -143,16 +131,6 @@ var HotelCalendarView = AbstractRenderer.extend({
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
$dateTimePickerBegin.datetimepicker(DTPickerOptions);
$dateTimePickerEnd.datetimepicker($.extend({}, DTPickerOptions, { 'useCurrent': false }));
$dateTimePickerBegin.on("dp.change", function (e) {
$dateTimePickerEnd.data("DateTimePicker").minDate(e.date.clone().add(3,'d'));
$dateTimePickerEnd.data("DateTimePicker").maxDate(e.date.clone().add(2,'M'));
$dateTimePickerBegin.data("DateTimePicker").hide();
self.on_change_filter_date(true);
});
$dateTimePickerEnd.on("dp.change", function (e) {
$dateTimePickerEnd.data("DateTimePicker").hide();
self.on_change_filter_date(false);
});
var date_begin = moment().startOf('day');
var days = date_begin.daysInMonth();
@@ -219,32 +197,6 @@ var HotelCalendarView = AbstractRenderer.extend({
self.do_action(this.dataset.action);
});
this.$el.find("#btn_swap").on('click', function(ev){
var hcalSwapMode = self._hcalendar.getSwapMode();
if (hcalSwapMode === HotelCalendar.MODE.NONE) {
self._hcalendar.setSwapMode(HotelCalendar.MODE.SWAP_FROM);
$("#btn_swap span.ntext").html(_t("CONTINUE"));
$("#btn_swap").css({
'backgroundColor': 'rgb(145, 255, 0)',
'fontWeight': 'bold'
});
} else if (self._hcalendar.getReservationAction().inReservations.length > 0 && hcalSwapMode === HotelCalendar.MODE.SWAP_FROM) {
self._hcalendar.setSwapMode(HotelCalendar.MODE.SWAP_TO);
$("#btn_swap span.ntext").html(_t("END"));
$("#btn_swap").css({
'backgroundColor': 'orange',
'fontWeight': 'bold'
});
} else {
self._hcalendar.setSwapMode(HotelCalendar.MODE.NONE);
$("#btn_swap span.ntext").html(_t("START SWAP"));
$("#btn_swap").css({
'backgroundColor': '',
'fontWeight': ''
});
}
});
return $.when(
this.trigger_up('onLoadCalendarSettings'),
this.trigger_up('onUpdateButtonsCounter'),
@@ -262,7 +214,7 @@ var HotelCalendarView = AbstractRenderer.extend({
theme: "classic"
});
$list.on('change', function(ev){
this._apply_filters();
this.trigger_up('onApplyFilters');
}.bind(this));
// Get Floors
@@ -273,7 +225,7 @@ var HotelCalendarView = AbstractRenderer.extend({
});
$list.select2();
$list.on('change', function(ev){
this._apply_filters();
this.trigger_up('onApplyFilters');
}.bind(this));
// Get Amenities
@@ -284,7 +236,7 @@ var HotelCalendarView = AbstractRenderer.extend({
});
$list.select2();
$list.on('change', function(ev){
this._apply_filters();
this.trigger_up('onApplyFilters');
}.bind(this));
// Get Virtual Rooms
@@ -295,7 +247,7 @@ var HotelCalendarView = AbstractRenderer.extend({
});
$list.select2();
$list.on('change', function(ev){
this._apply_filters();
this.trigger_up('onApplyFilters');
}.bind(this));
},
@@ -348,94 +300,6 @@ var HotelCalendarView = AbstractRenderer.extend({
$elm.val('');
},
on_change_filter_date: function(isStartDate) {
isStartDate = isStartDate || false;
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
// FIXME: Hackish onchange ignore (Used when change dates from code)
if ($dateTimePickerBegin.data("ignore_onchange") || $dateTimePickerEnd.data("ignore_onchange")) {
$dateTimePickerBegin.data("ignore_onchange", false);
$dateTimePickerEnd.data("ignore_onchange", false)
return true;
}
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone().utc();
if (this._hcalendar && date_begin) {
if (isStartDate) {
var ndate_end = date_begin.clone().add(this._view_options['days'], 'd');
$dateTimePickerEnd.data("ignore_onchange", true);
$dateTimePickerEnd.data("DateTimePicker").date(ndate_end.local());
}
if (!date_begin.isSame(this._last_dates[0].clone().utc(), 'd') || !date_end.isSame(this._last_dates[1].clone().utc(), 'd')) {
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().set({'hour': 23, 'minute': 59, 'second': 59}).clone().utc();
this._hcalendar.setStartDate(date_begin, this._hcalendar.getDateDiffDays(date_begin, date_end), false, function(){
this.reload_hcalendar_reservations(false);
}.bind(this));
}
}
},
reload_hcalendar_reservations: function(clearReservations) {
var filterDates = this.get_view_filter_dates();
// Clip dates
var dfrom = filterDates[0].clone(),
dto = filterDates[1].clone();
if (filterDates[0].isBetween(this._last_dates[0], this._last_dates[1], 'days') && filterDates[1].isAfter(this._last_dates[1], 'day')) {
dfrom = this._last_dates[1].clone().local().startOf('day').utc();
} else if (this._last_dates[0].isBetween(filterDates[0], filterDates[1], 'days') && this._last_dates[1].isAfter(filterDates[0], 'day')) {
dto = this._last_dates[0].clone().local().endOf('day').utc();
} else {
clearReservations = true;
}
return $.when(this.trigger_up('onReloadCalendar', {
oparams: [
dfrom.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
dto.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
false,
],
clearReservations: clearReservations,
})).then(function(){
this._last_dates = filterDates;
});
},
_apply_filters: function() {
var category = _.map(this.$el.find('#pms-search #type_list').val(), function(item){ return +item; });
var floor = _.map(this.$el.find('#pms-search #floor_list').val(), function(item){ return +item; });
var amenities = _.map(this.$el.find('#pms-search #amenities_list').val(), function(item){ return +item; });
var virtual = _.map(this.$el.find('#pms-search #virtual_list').val(), function(item){ return +item; });
var domain = [];
if (category && category.length > 0) {
domain.push(['class_name', 'in', category]);
}
if (floor && floor.length > 0) {
domain.push(['floor_id', 'in', floor]);
}
if (amenities && amenities.length > 0) {
domain.push(['amenities', 'in', amenities]);
}
if (virtual && virtual.length > 0) {
domain.push(['room_type_id', 'some', virtual]);
}
this._hcalendar.setDomain(HotelCalendar.DOMAIN.ROOMS, domain);
},
_merge_days_tooltips: function(new_tooltips) {
for (var nt of new_tooltips) {
var fnt = _.find(this._days_tooltips, function(item) { return item[0] === nt[0]});
if (fnt) {
fnt = nt;
} else {
this._days_tooltips.push(nt);
}
}
},
});
return HotelCalendarView;

View File

@@ -6,6 +6,9 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
var core = require('web.core');
var session = require('web.session');
var Widget = require('web.Widget');
var HotelConstants = require('hotel_calendar.Constants');
var QWeb = core.qweb;
var MultiCalendar = Widget.extend({
_calendars: [],
@@ -15,6 +18,7 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
_dataset: {},
_base: null,
init: function(parent) {
this._super.apply(this, arguments);
},
@@ -38,7 +42,7 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
},
get_active_calendar: function() {
return this._calendars[this._active_index];
return this._calendars[this._active_index-1];
},
get_active_tab: function() {
@@ -46,14 +50,23 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
},
recalculate_reservation_positions: function() {
setTimeout(function(){
for (var reserv of this.get_active_calendar()._reservations) {
var style = window.getComputedStyle(reserv._html, null);
if (parseInt(style.width, 10) < 15 || parseInt(style.height, 10) < 15 || parseInt(style.top, 10) === 0) {
this.get_active_calendar()._updateReservation(reserv);
var active_calendar = this.get_active_calendar();
if (active_calendar) {
setTimeout(function(calendar){
for (var reserv of calendar._reservations) {
var style = window.getComputedStyle(reserv._html, null);
if (parseInt(style.width, 10) < 15 || parseInt(style.height, 10) < 15 || parseInt(style.top, 10) === 0) {
this.get_active_calendar()._updateReservation(reserv);
}
}
}
}.bind(this), 200);
}.bind(this, active_calendar), 200);
}
},
remove_reservation: function(reserv_id) {
for (var calendar of this._calendars) {
calendar.removeReservation(reserv['reserv_id']);
}
},
update_all_reservations: function() {
@@ -64,11 +77,28 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
update_reservations: function(calendar) {
calendar.setReservations(this._dataset['reservations']);
this._assign_extra_info(calendar);
},
replace_reservation: function(newReserv, oldReserv) {
for (var calendar of this._calendars) {
calendar.replaceReservation(newReserv, oldReserv);
}
},
remove_obroom_row: function(reserv) {
for (var calendar of this._calendars) {
calendar.removeOBRoomRow(reserv);
}
},
swap_reservations: function(outReservs, inReservs) {
for (var calendar of this._calendars) {
calendar.swapReservations(outReservs, inReservs);
}
},
set_active_calendar: function(index) {
this._tabs[index][0].tab('show');
this._tabs[index+1][0].tab('show');
},
set_datasets: function(pricelist, restrictions, reservations) {
@@ -87,6 +117,79 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
this._base = element;
},
merge_pricelist: function(pricelist) {
var keys = _.keys(pricelist);
for (var k of keys) {
var pr = pricelist[k];
for (var pr_k in pr) {
var pr_item = pricelist[k][pr_k];
var pr_fk = _.findKey(this._dataset['pricelist'][k], {'room': pr_item.room});
if (pr_fk) {
this._dataset['pricelist'][k][pr_fk].room = pr_item.room;
this._dataset['pricelist'][k][pr_fk].days = _.extend(this._dataset['pricelist'][k][pr_fk].days, pr_item.days);
if (pr_item.title) {
this._dataset['pricelist'][k][pr_fk].title = pr_item.title;
}
} else {
if (!(k in this._dataset['pricelist'])) {
this._dataset['pricelist'][k] = [];
}
this._dataset['pricelist'][k].push({
'room': pr_item.room,
'days': pr_item.days,
'title': pr_item.title
});
}
}
}
for (var calendar of this._calendars) {
calendar.setPricelist(this._dataset['pricelist']);
}
},
merge_restrictions: function(restrictions) {
var room_type_ids = Object.keys(restrictions);
for (var vid of room_type_ids) {
if (vid in this._dataset['restrictions']) {
this._dataset['restrictions'][vid] = _.extend(this._dataset['restrictions'][vid], restrictions[vid]);
}
else {
this._dataset['restrictions'][vid] = restrictions[vid];
}
}
for (var calendar of this._calendars) {
calendar.setRestrictions(this._dataset['restrictions']);
}
},
merge_reservations: function(reservations) {
for (var r of reservations) {
var rindex = _.findKey(this._dataset['reservations'], {'id': r.id});
if (rindex) {
this._dataset['reservations'][rindex] = r;
} else {
this._dataset['reservations'].push(r);
}
}
for (var calendar of this._calendars) {
calendar.addReservations(_.clone(this._dataset['reservations']));
}
},
merge_days_tooltips: function(new_tooltips) {
for (var nt of new_tooltips) {
var fnt = _.find(this._days_tooltips, function(item) { return item[0] === nt[0]});
if (fnt) {
fnt = nt;
} else {
this._days_tooltips.push(nt);
}
}
},
create_calendar: function(name) {
var [$tab, $panel] = this._create_tab(name, `calendar-pane-${name}`);
var calendar = new HotelCalendar(
@@ -96,6 +199,8 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
this._dataset['restrictions'],
this._base);
this._assign_calendar_events(calendar);
this._assign_extra_info(calendar);
calendar.setReservations(_.clone(this._dataset['reservations']));
this._calendars.push(calendar);
return this._calendars.length-1;
},
@@ -106,6 +211,7 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
_create_tab: function(name, id) {
var self = this;
var sanitized_id = this._sanitizeId(id);
// '+' Tab
var $tab = $('<a/>', {
@@ -114,6 +220,10 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
text: name,
role: 'tab',
}).data('tabindex', this._tabs.length).appendTo($('<li/>').prependTo(this.$tabs));
$tab.on('shown.bs.tab', function(ev){
self._active_index = $(ev.target).data('tabindex');
self.recalculate_reservation_positions();
});
$tab[0].dataset.toggle = 'tab';
var $panel = $('<div/>', {
id: sanitized_id,

View File

@@ -197,9 +197,7 @@ HotelCalendar.prototype = {
},
addReservations: function(/*List*/reservations, /*Bool*/forced) {
if (!reservations) {
return;
}
reservations = reservations || [];
if (reservations.length > 0 && !(reservations[0] instanceof HReservation)) {
console.warn("[HotelCalendar][addReservations] Invalid Reservation definition!");
@@ -207,9 +205,11 @@ HotelCalendar.prototype = {
// Merge
var uzr = [];
for (var r of reservations) {
r = _.clone(r); // HOT-FIX: Multi-Calendar Support
var rindex = !forced?_.findKey(this._reservations, {'id': r.id}):false;
if (rindex) {
r._html = this._reservations[rindex]._html;
r.room = this._reservations[rindex].room;
if (this._reservations[rindex].overbooking && !r.overbooking) {
if (this.getReservationsByRoom(this._reservations[rindex].room).length === 1) {
this.removeOBRoomRow(this._reservations[rindex]);
@@ -225,6 +225,7 @@ HotelCalendar.prototype = {
this.createOBRoomRow(room);
}
if (room) {
r.room = room;
this._reservations.push(r);
} else {
console.warn(`Can't found a room for the reservation '${r[0]}'!`);
@@ -264,7 +265,7 @@ HotelCalendar.prototype = {
}
this._updateReservation(r);
}
}.bind(this), reservations);
}.bind(this), this._reservations);
_.defer(function(){ this._updateReservationOccupation(); }.bind(this));
}
@@ -700,19 +701,6 @@ HotelCalendar.prototype = {
this._updateRestrictions();
},
addRestrictions: function(/*Object*/restrictions) {
var room_type_ids = Object.keys(restrictions);
for (var vid of room_type_ids) {
if (vid in this._restrictions) {
this._restrictions[vid] = _.extend(this._restrictions[vid], restrictions[vid]);
}
else {
this._restrictions[vid] = restrictions[vid];
}
}
this._updateRestrictions();
},
_updateRestrictions: function() {
// Clean
var restDays = this.e.querySelectorAll('.hcal-restriction-room-day');
@@ -2093,34 +2081,6 @@ HotelCalendar.prototype = {
this._updatePriceList();
},
addPricelist: function(/*Dictionary*/pricelist) {
var keys = _.keys(pricelist);
for (var k of keys) {
var pr = pricelist[k];
for (var pr_k in pr) {
var pr_item = pricelist[k][pr_k];
var pr_fk = _.findKey(this._pricelist[k], {'room': pr_item.room});
if (pr_fk) {
this._pricelist[k][pr_fk].room = pr_item.room;
this._pricelist[k][pr_fk].days = _.extend(this._pricelist[k][pr_fk].days, pr_item.days);
if (pr_item.title) {
this._pricelist[k][pr_fk].title = pr_item.title;
}
} else {
if (!(k in this._pricelist)) {
this._pricelist[k] = [];
}
this._pricelist[k].push({
'room': pr_item.room,
'days': pr_item.days,
'title': pr_item.title
});
}
}
}
this._updatePriceList();
},
updateRoomTypePrice: function(pricelist_id, room_type_id, date, price) {
var strDate = date.format(HotelCalendar.DATE_FORMAT_SHORT_);
var cellId = this._sanitizeId(`CELL_PRICE_${pricelist_id}_${room_type_id}_${strDate}`);
@@ -2248,8 +2208,7 @@ HotelCalendar.prototype = {
_dispatchEvent: function(/*String*/eventName, /*Dictionary*/data) {
this.e.dispatchEvent(new CustomEvent(eventName, {
'detail': data,
'calendar': this,
detail: _.extend({calendar_obj: this}, data),
}));
},
@@ -2753,7 +2712,7 @@ HRoom.prototype = {
/** RESERVATION OBJECT **/
function HReservation(/*Dictionary*/rValues) {
if (typeof rValues.room === 'undefined') {
if (typeof rValues.room_id === 'undefined' && typeof rValues.room === 'undefined') {
delete this;
console.warn("[Hotel Calendar][HReservation] room can't be empty!");
return;
@@ -2775,6 +2734,7 @@ function HReservation(/*Dictionary*/rValues) {
this.linkedId = rValues.linkedId || -1;
this.splitted = rValues.splitted || false;
this.overbooking = rValues.overbooking || false;
this.room = rValues.room || null;
this._drawModes = ['hard-start', 'hard-end'];
this._html = false;
@@ -2826,7 +2786,8 @@ HReservation.prototype = {
'unusedZone': this.unusedZone,
'linkedId': this.linkedId,
'splitted': this.splitted,
'overbooking': this.overbooking
'overbooking': this.overbooking,
'room_id': this.room_id,
});
nreserv._beds = _.clone(this._beds);
nreserv._html = this._html;