[WIP] New Calendar Theme

This commit is contained in:
QS5ELkMu
2018-12-12 04:25:53 +01:00
parent 8784f982c8
commit 4091dc0522
12 changed files with 566 additions and 575 deletions

View File

@@ -133,6 +133,7 @@ class HotelReservation(models.Model):
'name': room.name,
'capacity': room.capacity,
'class_name': room.room_type_id.class_id.name,
'class_id': room.room_type_id.class_id.id,
'shared': room.shared_room,
'price': room.room_type_id
and ['pricelist', room.room_type_id.id, pricelist_id,
@@ -151,6 +152,10 @@ class HotelReservation(models.Model):
json_calendars.append({
'id': calendar.id,
'name': calendar.name,
'segmentation_ids': calendar.segmentation_ids.ids,
'location_ids': calendar.location_ids.ids,
'amenity_ids': calendar.amenity_ids.ids,
'room_type_ids': calendar.room_type_ids.ids,
})
return json_calendars

View File

@@ -18,53 +18,89 @@
#pms-menu {
padding: 0 0.2em !important;
}
#pms-menu .input-group span, #pms-menu input {
border-radius: 0;
}
#pms-menu button {
min-height: 45px;
margin: 0.2em 0;
border-radius: 0;
border: 1px solid lightgray;
font-size: x-small;
}
#pms-search {
padding: 0.5em !important;
background-color: white;
box-shadow: 10px 1px 12px #333;
}
#pms-search fieldset {
button .led {
position: absolute;
display: inline-block;
right: 5px;
top: -1px;
width: 8px;
height: 8px;
border: 1px solid lightgray;
border-top-width: 0;
border-top-right-radius: 0;
border-top-left-radius: 0;
transition: all 0.5s ease;
}
#pms-search fieldset legend {
font-size: initial !important;
margin: initial !important;
button .led-disabled {
background-color: dimgrey;
}
#pms-search .list {
overflow-y: auto;
button .led-enabled {
background-color: khaki;
box-shadow: 0 0 8px 0px khaki;
}
button .led-green {
background-color: chartreuse;
box-shadow: 0 0 8px 0px chartreuse;
}
button .led-blue {
background-color: cornflowerblue;
box-shadow: 0 0 8px 0px cornflowerblue;
}
input#bookings_search {
border-top-left-radius: 0;
border-top-right-radius: 0;
border: 1px solid lightgray;
}
#pms-menu .menu-date-box {
margin-top: 2px !important;
}
#pms-menu .menu-button-box, #pms-menu .menu-search-box, #pms-menu .menu-filter-box {
margin-top: 2em !important;
}
#pms-menu .menu-filter-box .filter-record {
margin-top: 1em;
}
#pms-menu .button-box {
text-align: left;
}
#pms-search label {
font-size: 12px;
min-height: 3.5em;
padding: 3px;
transition: all 0.5s ease;
}
#pms-search-table > tbody > tr > td {
background-color: white;
padding: 0.1em;
border: 1px solid #efefef;
border-width: 0 2px;
vertical-align: middle;
text-align: center;
.button-highlight {
background-color: orange;
color: white;
}
#pms-search-table > tbody > tr > td:first-child {
border-width: 0 2px 0 0;
}
#pms-search-table > tbody > tr > td:last-child {
border-width: 0 0 0 2px;
.button-highlight i {
color: white;
}
#pms-search-cal-pag .btn {
background-color: transparent;
padding: 0.1em;
.multi-calendar-tab-plus {
background-color: darkgray;
font-weight: bold;
color: white;
}
.input-group {
padding: 0.1em;
#pms-menu div[id^=btn_] {
padding: 2px;
}
.warn-message {
@@ -75,29 +111,33 @@
}
/** SELECT 2 **/
#pms-search .select2-search-choice {
padding-top: 1px !important;
padding-bottom: 1px !important;
font-size: 10px !important;
#pms-menu .select2-container {
border-radius: 0;
}
#pms-search .select2-search-choice-close {
top: 1px !important;
}
/** BOOTSTRAP **/
.badge-danger {
background-color: #d34f2a !important;
}
/** FONT AWESOME **/
.cloud-text {
margin-top: .12em;
font-size: 26px;
font-family: sans-serif;
font-weight: bold;
}
/** ODOO **/
.o_chat_window {
z-index: 8 !important;
}
.o_button_icon {
display: inline-block;
width: 37px;
padding: 0px 3px;
text-align: center;
vertical-align: middle;
color: #7C7BAD;
font-size: 24px;
}
.o_button_text {
display: inline-block;
vertical-align: middle;
max-width: 70%;
line-height: 1.2;
text-align: left;
}

View File

@@ -44,7 +44,9 @@ var PMSCalendarController = AbstractController.extend({
this._multi_calendar.setElement(this.renderer.$el.find('#hcal_widget'));
this._multi_calendar.start();
this._multi_calendar.on('tab_changed', function(ev, active_index){
self._refresh_filters(active_index);
if (active_index) {
self._refresh_filters(active_index);
}
});
this._assign_multi_calendar_events();
this._load_calendars();
@@ -110,7 +112,7 @@ var PMSCalendarController = AbstractController.extend({
'room_type_id': r['room_type_id'],
'floor_id': r['floor_id'],
'amenities': r['amenity_ids'],
'class_name': r['class_name']
'class_id': r['class_id'],
});
rooms.push(nroom);
}
@@ -159,13 +161,33 @@ var PMSCalendarController = AbstractController.extend({
self._multi_calendar.set_datasets(results['pricelist'], results['restrictions'], reservs);
self._multi_calendar.set_base_element(self.renderer.$el[0]);
for (var calendar of results['calendars']) {
self._multi_calendar.create_calendar(calendar['name']);
for (var calendar_record of results['calendars']) {
var calendar_index = self._multi_calendar.create_calendar(calendar_record);
var domain = self._generate_calendar_filters_domain(calendar_record);
var calendar = self._multi_calendar.get_calendar(calendar_index+1);
calendar.setDomain(HotelCalendar.DOMAIN.ROOMS, domain);
}
self._multi_calendar.set_active_calendar(self._multi_calendar._calendars.length-1);
});
},
_generate_calendar_filters_domain: function(calendar) {
var domain = [];
if (calendar['segmentation_ids'] && calendar['segmentation_ids'].length > 0) {
domain.push(['class_id', 'in', calendar['segmentation_ids']]);
}
if (calendar['location_ids'] && calendar['location_ids'].length > 0) {
domain.push(['floor_id', 'in', calendar['location_ids']]);
}
if (calendar['amenity_ids'] && calendar['amenity_ids'].length > 0) {
domain.push(['amenities', 'in', calendar['amenity_ids']]);
}
if (calendar['room_type_ids'] && calendar['room_type_ids'].length > 0) {
domain.push(['room_type_id', 'some', calendar['room_type_ids']]);
}
return domain;
},
_reload_active_calendar: function() {
var self = this;
var filterDates = this.renderer.get_view_filter_dates();
@@ -223,8 +245,8 @@ var PMSCalendarController = AbstractController.extend({
_assign_view_events: function() {
var self = this;
var $dateTimePickerBegin = this.renderer.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.renderer.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-menu #date_end');
$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'));
@@ -236,32 +258,75 @@ var PMSCalendarController = AbstractController.extend({
self._on_change_filter_date(false);
});
this.renderer.$el.find("#btn_swap").on('click', function(ev){
this.renderer.$el.find("#btn_swap button").on('click', function(ev){
var active_calendar = self._multi_calendar.get_active_calendar();
var hcalSwapMode = active_calendar.getSwapMode();
var $led = $(this).find('.led');
if (hcalSwapMode === HotelCalendar.MODE.NONE) {
active_calendar.setSwapMode(HotelCalendar.MODE.SWAP_FROM);
$("#btn_swap span.ntext").html(_t("CONTINUE"));
$("#btn_swap").css({
'backgroundColor': 'rgb(145, 255, 0)',
'fontWeight': 'bold'
});
$("#btn_swap span.ntext").html(_t("Continue"));
$led.removeClass('led-disabled');
$led.addClass('led-green');
} else if (active_calendar.getReservationAction().inReservations.length > 0 && hcalSwapMode === HotelCalendar.MODE.SWAP_FROM) {
active_calendar.setSwapMode(HotelCalendar.MODE.SWAP_TO);
$("#btn_swap span.ntext").html(_t("END"));
$("#btn_swap").css({
'backgroundColor': 'orange',
'fontWeight': 'bold'
});
$("#btn_swap span.ntext").html(_t("End"));
$led.removeClass('led-green');
$led.addClass('led-blue');
} else {
active_calendar.setSwapMode(HotelCalendar.MODE.NONE);
$("#btn_swap span.ntext").html(_t("START SWAP"));
$("#btn_swap").css({
'backgroundColor': '',
'fontWeight': ''
});
$("#btn_swap span.ntext").html(_t("Start Swap"));
$led.removeClass('led-blue');
$led.addClass('led-disabled');
}
});
this.renderer.$el.find('#pms-menu #btn_action_overbooking button').on('click', function(ev){
var active_calendar = self._multi_calendar.get_active_calendar();
active_calendar.toggleOverbookingsVisibility();
active_calendar.addReservations(self._multi_calendar._dataset['reservations']);
if (active_calendar.options.showOverbookings) {
$(this).find('.led').removeClass('led-disabled');
$(this).find('.led').addClass('led-enabled');
} else {
$(this).find('.led').addClass('led-disabled');
$(this).find('.led').removeClass('led-enabled');
}
});
this.renderer.$el.find('#pms-menu #btn_action_cancelled button').on('click', function(ev){
var active_calendar = self._multi_calendar.get_active_calendar();
active_calendar.toggleCancelledVisibility();
active_calendar.addReservations(self._multi_calendar._dataset['reservations']);
});
this.renderer.$el.find('#pms-menu #btn_save_calendar_record').on('click', function(ev){
var active_calendar_record = self._multi_calendar.get_calendar_record(self._multi_calendar.get_active_index());
active_calendar_record.name = "LOLO";
var name = self.renderer.$el.find('#pms-menu #calendar_name').val();
var category = _.map(self.renderer.$el.find('#pms-menu #type_list').val(), function(item){ return +item; });
var floor = _.map(self.renderer.$el.find('#pms-menu #floor_list').val(), function(item){ return +item; });
var amenities = _.map(self.renderer.$el.find('#pms-menu #amenities_list').val(), function(item){ return +item; });
var types = _.map(self.renderer.$el.find('#pms-menu #virtual_list').val(), function(item){ return +item; });
var oparams = {
'name': name,
'segmentation_ids': [[6, false, category]],
'location_ids': [[6, false, floor]],
'amenity_ids': [[6, false, amenities]],
'room_type_ids': [[6, false, types]],
}
self._multi_calendar.update_active_tab_name(name);
self.model.update_or_create_calendar_record(active_calendar_record['id'], oparams).then(function(){
active_calendar_record.name = name;
active_calendar_record.segmentation_ids = category;
active_calendar_record.location_ids = floor;
active_calendar_record.amenity_ids = amenities;
active_calendar_record.room_type_ids = types;
}).fail(function(){
self._multi_calendar.update_active_tab_name(active_calendar_record.name);
});
});
},
_assign_multi_calendar_events: function() {
@@ -358,11 +423,9 @@ var PMSCalendarController = AbstractController.extend({
}).open();
});
this._multi_calendar.on_calendar('hcalOnCancelSwapReservations', function(ev){
$("#btn_swap span.ntext").html(_t("START SWAP"));
$("#btn_swap").css({
'backgroundColor': '',
'fontWeight': 'normal'
});
$("#btn_swap span.ntext").html(_t("Start Swap"));
var $led = $("#btn_swap").find('.led');
$led.removeClass('led-blue').removeClass('led-green').addClass('led-disabled');
});
this._multi_calendar.on_calendar('hcalOnChangeReservation', function(ev){
var newReservation = ev.detail.newReserv;
@@ -429,10 +492,10 @@ var PMSCalendarController = AbstractController.extend({
for (var td of ev.detail.old_cells) {
$(td).tooltip('destroy');
}
if (ev.detail.cells.length > 1) {
if (ev.detail.cells.length) {
var last_cell = ev.detail.cells[ev.detail.cells.length-1];
var date_cell_start = HotelCalendar.toMoment(ev.detail.calendar_obj.etable.querySelector(`#${ev.detail.cells[0].dataset.hcalParentCell}`).dataset.hcalDate);
var date_cell_end = HotelCalendar.toMoment(ev.detail.calendar_obj.etable.querySelector(`#${last_cell.dataset.hcalParentCell}`).dataset.hcalDate);
var date_cell_end = HotelCalendar.toMoment(ev.detail.calendar_obj.etable.querySelector(`#${last_cell.dataset.hcalParentCell}`).dataset.hcalDate).add(1, 'd');
var parentRow = document.querySelector(`#${ev.detail.cells[0].dataset.hcalParentRow}`);
var room = ev.detail.calendar_obj.getRoom(parentRow.dataset.hcalRoomObjId);
if (room.overbooking) {
@@ -456,7 +519,7 @@ var PMSCalendarController = AbstractController.extend({
var parentCellStart = document.querySelector(`#${ev.detail.cellStart.dataset.hcalParentCell}`);
var parentCellEnd = document.querySelector(`#${ev.detail.cellEnd.dataset.hcalParentCell}`);
var startDate = HotelCalendar.toMoment(parentCellStart.dataset.hcalDate);
var endDate = HotelCalendar.toMoment(parentCellEnd.dataset.hcalDate);
var endDate = HotelCalendar.toMoment(parentCellEnd.dataset.hcalDate).add(1, 'd');
var room = ev.detail.calendar_obj.getRoom(parentRow.dataset.hcalRoomObjId);
if (room.overbooking) {
return;
@@ -495,8 +558,8 @@ var PMSCalendarController = AbstractController.extend({
});
this._multi_calendar.on_calendar('hcalOnDateChanged', function(ev){
var $dateTimePickerBegin = this.renderer.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.renderer.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-menu #date_end');
$dateTimePickerBegin.data("ignore_onchange", true);
$dateTimePickerEnd.data("DateTimePicker").minDate(false);
$dateTimePickerEnd.data("DateTimePicker").maxDate(false);
@@ -653,13 +716,13 @@ var PMSCalendarController = AbstractController.extend({
},
_onApplyFilters: function() {
var category = _.map(this.renderer.$el.find('#pms-search #type_list').val(), function(item){ return +item; });
var floor = _.map(this.renderer.$el.find('#pms-search #floor_list').val(), function(item){ return +item; });
var amenities = _.map(this.renderer.$el.find('#pms-search #amenities_list').val(), function(item){ return +item; });
var virtual = _.map(this.renderer.$el.find('#pms-search #virtual_list').val(), function(item){ return +item; });
var category = _.map(this.renderer.$el.find('#pms-menu #type_list').val(), function(item){ return +item; });
var floor = _.map(this.renderer.$el.find('#pms-menu #floor_list').val(), function(item){ return +item; });
var amenities = _.map(this.renderer.$el.find('#pms-menu #amenities_list').val(), function(item){ return +item; });
var virtual = _.map(this.renderer.$el.find('#pms-menu #virtual_list').val(), function(item){ return +item; });
var domain = [];
if (category && category.length > 0) {
domain.push(['class_name', 'in', category]);
domain.push(['class_id', 'in', category]);
}
if (floor && floor.length > 0) {
domain.push(['floor_id', 'in', floor]);
@@ -670,254 +733,9 @@ var PMSCalendarController = AbstractController.extend({
if (virtual && virtual.length > 0) {
domain.push(['room_type_id', 'some', virtual]);
}
this._multi_calendar.get_active_calendar().setDomain(HotelCalendar.DOMAIN.ROOMS, domain);
},
_assign_hcalendar_events: function() {
var self = this;
this._multi_calendar.on_calendar('hcalOnSavePricelist', function(ev){
var oparams = [ev.detail.pricelist_id, false, ev.detail.pricelist, {}, {}];
self.savePricelist(ev.detail.calendar_obj, ev.detail.pricelist_id, ev.detail.pricelist);
});
this._multi_calendar.on_calendar('hcalOnMouseEnterReservation', function(ev){
if (ev.detail.reservationObj) {
var tp = self._multi_calendar._reserv_tooltips[ev.detail.reservationObj.id];
var qdict = self._generate_reservation_tooltip_dict(tp);
$(ev.detail.reservationDiv).tooltip('destroy').tooltip({
animation: false,
html: true,
placement: 'bottom',
title: QWeb.render('HotelCalendar.TooltipReservation', qdict)
}).tooltip('show');
}
});
this._multi_calendar.on_calendar('hcalOnClickReservation', function(ev){
//var res_id = ev.detail.reservationObj.getUserData('folio_id');
$(ev.detail.reservationDiv).tooltip('hide');
self.do_action({
type: 'ir.actions.act_window',
res_model: 'hotel.reservation',
res_id: ev.detail.reservationObj.id,
views: [[false, 'form']]
});
// self._model.call('get_formview_id', [res_id, Session.user_context]).then(function(view_id){
// var pop = new ViewDialogs.FormViewDialog(self, {
// res_model: 'hotel.folio',
// res_id: res_id,
// title: _t("Open: ") + ev.detail.reservationObj.title,
// view_id: view_id
// //readonly: false
// }).open();
// pop.on('write_completed', self, function(){
// self.trigger('changed_value');
// });
// });
});
this._multi_calendar.on_calendar('hcalOnSwapReservations', function(ev){
var qdict = {};
var dialog = new Dialog(self, {
title: _t("Confirm Reservation Swap"),
buttons: [
{
text: _t("Yes, swap it"),
classes: 'btn-primary',
close: true,
click: function () {
if (ev.detail.calendar_obj.swapReservations(ev.detail.inReservs, ev.detail.outReservs)) {
var fromIds = _.pluck(ev.detail.inReservs, 'id');
var toIds = _.pluck(ev.detail.outReservs, 'id');
var refFromReservDiv = ev.detail.inReservs[0]._html;
var refToReservDiv = ev.detail.outReservs[0]._html;
// Animate Movement
for (var nreserv of ev.detail.inReservs) {
$(nreserv._html).animate({'top': refToReservDiv.style.top});
}
for (var nreserv of ev.detail.outReservs) {
$(nreserv._html).animate({'top': refFromReservDiv.style.top});
}
self.trigger_up('onSwapReservations', {
'fromIds': fromIds,
'toIds': toIds,
'detail': ev.detail,
'refFromReservDiv': refFromReservDiv,
'refToReservDiv': refToReservDiv
});
} else {
var qdict = {};
var dialog = new Dialog(self, {
title: _t("Invalid Reservation Swap"),
buttons: [
{
text: _t("Oops, Ok!"),
classes: 'btn-primary',
close: true
}
],
$content: QWeb.render('HotelCalendar.InvalidSwapOperation', qdict)
}).open();
}
}
},
{
text: _t("No"),
close: true
}
],
$content: QWeb.render('HotelCalendar.ConfirmSwapOperation', qdict)
}).open();
});
this._multi_calendar.on_calendar('hcalOnCancelSwapReservations', function(ev){
$("#btn_swap span.ntext").html(_t("START SWAP"));
$("#btn_swap").css({
'backgroundColor': '',
'fontWeight': 'normal'
});
});
this._multi_calendar.on_calendar('hcalOnChangeReservation', function(ev){
var newReservation = ev.detail.newReserv;
var oldReservation = ev.detail.oldReserv;
var oldPrice = ev.detail.oldPrice;
var newPrice = ev.detail.newPrice;
var folio_id = newReservation.getUserData('folio_id');
var linkedReservs = _.find(ev.detail.calendar_obj._reservations, function(item){
return item.id !== newReservation.id && !item.unusedZone && item.getUserData('folio_id') === folio_id;
});
var hasChanged = false;
var qdict = {
ncheckin: newReservation.startDate.clone().local().format(HotelConstants.L10N_DATETIME_MOMENT_FORMAT),
ncheckout: newReservation.endDate.clone().local().format(HotelConstants.L10N_DATETIME_MOMENT_FORMAT),
nroom: newReservation.room.number,
nprice: newPrice,
ocheckin: oldReservation.startDate.clone().local().format(HotelConstants.L10N_DATETIME_MOMENT_FORMAT),
ocheckout: oldReservation.endDate.clone().local().format(HotelConstants.L10N_DATETIME_MOMENT_FORMAT),
oroom: oldReservation.room.number,
oprice: oldPrice,
hasReservsLinked: (linkedReservs && linkedReservs.length !== 0)?true:false
};
var dialog = new Dialog(self, {
title: _t("Confirm Reservation Changes"),
buttons: [
{
text: _t("Yes, change it"),
classes: 'btn-primary',
close: true,
disabled: !newReservation.id,
click: function () {
var roomId = newReservation.room.id;
if (newReservation.room.overbooking) {
roomId = +newReservation.room.id.substr(newReservation.room.id.indexOf('@')+1);
}
var write_values = {
'checkin': newReservation.startDate.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
'checkout': newReservation.endDate.format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
'room_id': roomId,
'overbooking': newReservation.room.overbooking
};
self.updateReservations([newReservation.id], write_values,
oldReservation, newReservation);
hasChanged = true;
}
},
{
text: _t("No"),
close: true,
}
],
$content: QWeb.render('HotelCalendar.ConfirmReservationChanges', qdict)
}).open();
dialog.on('closed', this, function(e){
if (!hasChanged) {
self._multicalendar.replace_reservation(newReservation, oldReservation);
}
});
});
this._multi_calendar.on_calendar('hcalOnUpdateSelection', function(ev){
for (var td of ev.detail.old_cells) {
$(td).tooltip('destroy');
}
if (ev.detail.cells.length > 1) {
var last_cell = ev.detail.cells[ev.detail.cells.length-1];
var date_cell_start = HotelCalendar.toMoment(ev.detail.calendar_obj.etable.querySelector(`#${ev.detail.cells[0].dataset.hcalParentCell}`).dataset.hcalDate);
var date_cell_end = HotelCalendar.toMoment(ev.detail.calendar_obj.etable.querySelector(`#${last_cell.dataset.hcalParentCell}`).dataset.hcalDate);
var parentRow = document.querySelector(`#${ev.detail.cells[0].dataset.hcalParentRow}`);
var room = ev.detail.calendar_obj.getRoom(parentRow.dataset.hcalRoomObjId);
if (room.overbooking) {
return;
}
var nights = date_cell_end.diff(date_cell_start, 'days');
var qdict = {
'total_price': Number(ev.detail.totalPrice).toLocaleString(),
'nights': nights
};
$(last_cell).tooltip({
animation: false,
html: true,
placement: 'top',
title: QWeb.render('HotelCalendar.TooltipSelection', qdict)
}).tooltip('show');
}
});
this._multi_calendar.on_calendar('hcalOnChangeSelection', function(ev){
var parentRow = document.querySelector(`#${ev.detail.cellStart.dataset.hcalParentRow}`);
var parentCellStart = document.querySelector(`#${ev.detail.cellStart.dataset.hcalParentCell}`);
var parentCellEnd = document.querySelector(`#${ev.detail.cellEnd.dataset.hcalParentCell}`);
var startDate = HotelCalendar.toMoment(parentCellStart.dataset.hcalDate);
var endDate = HotelCalendar.toMoment(parentCellEnd.dataset.hcalDate);
var room = ev.detail.calendar_obj.getRoom(parentRow.dataset.hcalRoomObjId);
if (room.overbooking) {
return;
}
var numBeds = (room.shared || ev.detail.calendar_obj.getOptions('divideRoomsByCapacity'))?(ev.detail.cellEnd.dataset.hcalBedNum - ev.detail.cellStart.dataset.hcalBedNum)+1:room.capacity;
if (numBeds <= 0) {
return;
}
// Normalize Dates
if (startDate.isAfter(endDate)) {
var tt = endDate;
endDate = startDate;
startDate = tt;
}
var def_arrival_hour = self._view_options['default_arrival_hour'].split(':');
var def_departure_hour = self._view_options['default_departure_hour'].split(':');
startDate.set({'hour': def_arrival_hour[0], 'minute': def_arrival_hour[1], 'second': 0});
endDate.set({'hour': def_departure_hour[0], 'minute': def_departure_hour[1], 'second': 0});
var popCreate = new ViewDialogs.FormViewDialog(self, {
res_model: 'hotel.reservation',
context: {
'default_checkin': startDate.utc().format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
'default_checkout': endDate.utc().format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT),
'default_adults': numBeds,
'default_children': 0,
'default_room_id': room.id,
'default_room_type_id': room.getUserData('room_type_id'),
},
title: _t("Create: ") + _t("Reservation"),
initial_view: "form",
disable_multiple_selection: true,
}).open();
});
this._multi_calendar.on_calendar('hcalOnDateChanged', function(ev){
var $dateTimePickerBegin = this.renderer.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-search #date_end');
$dateTimePickerBegin.data("ignore_onchange", true);
$dateTimePickerEnd.data("DateTimePicker").minDate(false);
$dateTimePickerEnd.data("DateTimePicker").maxDate(false);
$dateTimePickerBegin.data("DateTimePicker").date(ev.detail.date_begin.local().add(1, 'd'));
$dateTimePickerEnd.data("ignore_onchange", true);
$dateTimePickerEnd.data("DateTimePicker").date(ev.detail.date_end.local());
this._reload_active_calendar();
}.bind(this));
},
_generate_reservation_tooltip_dict: function(tp) {
return {
'name': tp[0],
@@ -932,8 +750,8 @@ var PMSCalendarController = AbstractController.extend({
_on_change_filter_date: function(isStartDate) {
isStartDate = isStartDate || false;
var $dateTimePickerBegin = this.renderer.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.renderer.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-menu #date_end');
// FIXME: Hackish onchange ignore (Used when change dates from code)
if ($dateTimePickerBegin.data("ignore_onchange") || $dateTimePickerEnd.data("ignore_onchange")) {
@@ -963,8 +781,10 @@ var PMSCalendarController = AbstractController.extend({
_refresh_filters: function(active_index) {
var active_calendar = this._multi_calendar.get_calendar(active_index);
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
/* Dates */
var $dateTimePickerBegin = this.renderer.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.renderer.$el.find('#pms-menu #date_end');
var start_date = active_calendar.getOptions('startDate');
var end_date = start_date.clone().add(active_calendar.getOptions('days'), 'd');
@@ -974,6 +794,34 @@ var PMSCalendarController = AbstractController.extend({
$dateTimePickerBegin.data("DateTimePicker").date(start_date.local());
$dateTimePickerEnd.data("ignore_onchange", true);
$dateTimePickerEnd.data("DateTimePicker").date(end_date.local());
/* Overbooking Led */
var $led = this.renderer.$el.find('#pms-menu #btn_action_overbooking button .led');
if (active_calendar.options.showOverbookings) {
$led.removeClass('led-disabled').addClass('led-enabled');
} else {
$led.removeClass('led-enabled').addClass('led-disabled');
}
/* Calendar Record */
var active_calendar_record = this._multi_calendar.get_calendar_record(active_index);
var $calendar_name = this.renderer.$el.find('#pms-menu .menu-filter-box #calendar_name');
$calendar_name.val(active_calendar_record['name']);
/* Calendar Filters */
var active_filters = this._multi_calendar.get_active_filters();
var $segmentation = this.renderer.$el.find('#pms-menu #type_list');
var $location = this.renderer.$el.find('#pms-menu #floor_list');
var $amenities = this.renderer.$el.find('#pms-menu #amenities_list');
var $types = this.renderer.$el.find('#pms-menu #virtual_list');
$segmentation.val(active_filters['class_id']);
$segmentation.trigger('change');
$location.val(active_filters['floor_id']);
$location.trigger('change');
$amenities.val(active_filters['amenities']);
$amenities.trigger('change');
$types.val(active_filters['room_type_id']);
$types.trigger('change');
},
_find_bootstrap_environment: function() {

View File

@@ -106,6 +106,23 @@ return AbstractModel.extend({
});
},
update_or_create_calendar_record: function(ids, vals) {
if (!ids) {
return this._rpc({
model: 'hotel.calendar',
method: 'create',
args: [vals],
context: Session.user_context,
});
}
return this._rpc({
model: 'hotel.calendar',
method: 'write',
args: [ids, vals],
context: Session.user_context,
});
},
folio_search_count: function(domain) {
return this._rpc({
model: 'hotel.folio',

View File

@@ -52,8 +52,8 @@ var HotelCalendarView = AbstractRenderer.extend({
/** CUSTOM METHODS **/
get_view_filter_dates: function () {
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-menu #date_end');
var date_begin = $dateTimePickerBegin.data("DateTimePicker").date().set({'hour': 0, 'minute': 0, 'second': 0}).clone().utc();
var date_end = $dateTimePickerEnd.data("DateTimePicker").date().set({'hour': 23, 'minute': 59, 'second': 59}).clone().utc();
@@ -65,8 +65,8 @@ var HotelCalendarView = AbstractRenderer.extend({
this._view_options = options;
var date_begin = moment().startOf('day');
var date_end = date_begin.clone().add(this._view_options['days'], 'd').endOf('day');
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-menu #date_end');
//$dateTimePickerBegin.data("ignore_onchange", true);
$dateTimePickerBegin.data("DateTimePicker").date(date_begin);
//$dateTimePickerEnd.data("ignore_onchange", true);
@@ -77,36 +77,30 @@ var HotelCalendarView = AbstractRenderer.extend({
update_buttons_counter: function(ncheckouts, ncheckins, noverbookings) {
var self = this;
// Checkouts Button
var $ninfo = self.$el.find('#pms-menu #btn_action_checkout div.ninfo');
var $badge_checkout = $ninfo.find('.badge');
if (ncheckouts > 0) {
$badge_checkout.text(ncheckouts);
$badge_checkout.parent().show();
$ninfo.show();
var $ninfo = self.$el.find('#pms-menu #btn_action_checkout span.ninfo');
$ninfo.text(ncheckouts);
if (ncheckouts) {
$ninfo.parent().parent().addClass('button-highlight');
} else {
$ninfo.hide();
$ninfo.parent().parent().removeClass('button-highlight');
}
// Checkins Button
$ninfo = self.$el.find('#pms-menu #btn_action_checkin div.ninfo');
var $badge_checkin = $ninfo.find('.badge');
if (ncheckins > 0) {
$badge_checkin.text(ncheckins);
$badge_checkin.parent().show();
$ninfo.show();
$ninfo = self.$el.find('#pms-menu #btn_action_checkin span.ninfo');
$ninfo.text(ncheckins);
if (ncheckins) {
$ninfo.parent().parent().addClass('button-highlight');
} else {
$ninfo.hide();
$ninfo.parent().parent().removeClass('button-highlight');
}
// OverBookings
$ninfo = self.$el.find('#pms-menu #btn_swap div.ninfo');
var $badge_swap = $ninfo.find('.badge');
if (noverbookings > 0) {
$badge_swap.text(noverbookings);
$badge_swap.parent().show();
$ninfo.show();
$ninfo = self.$el.find('#pms-menu #btn_action_overbooking span.ninfo');
$ninfo.text(noverbookings);
if (noverbookings) {
$ninfo.parent().parent().addClass('button-highlight');
} else {
$ninfo.hide();
$ninfo.parent().parent().removeClass('button-highlight');
}
},
@@ -127,8 +121,8 @@ var HotelCalendarView = AbstractRenderer.extend({
locale : moment.locale(),
format : HotelConstants.L10N_DATE_MOMENT_FORMAT,
};
var $dateTimePickerBegin = this.$el.find('#pms-search #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-search #date_end');
var $dateTimePickerBegin = this.$el.find('#pms-menu #date_begin');
var $dateTimePickerEnd = this.$el.find('#pms-menu #date_end');
$dateTimePickerBegin.datetimepicker(DTPickerOptions);
$dateTimePickerEnd.datetimepicker($.extend({}, DTPickerOptions, { 'useCurrent': false }));
@@ -140,21 +134,6 @@ var HotelCalendarView = AbstractRenderer.extend({
$dateTimePickerEnd.data("DateTimePicker").date(date_end);
this._last_dates = this.get_view_filter_dates();
// Initial State
var $pms_search = this.$el.find('#pms-search');
$pms_search.css({
'top': `-100%`,
'opacity': 0.0,
});
// Show search (Alt+S)
$(document).keydown(function(ev){
if (ev.altKey){
if (ev.key == 'x' || ev.key == 'X'){
self.toggle_pms_search();
}
}
});
/* TOUCH EVENTS */
this.$el.on('touchstart', function(ev){
var orgEvent = ev.originalEvent;
@@ -185,13 +164,19 @@ var HotelCalendarView = AbstractRenderer.extend({
/* BUTTONS */
var $button = this.$el.find('#pms-menu #btn_action_bookings');
$button.on('click', function(ev){ self._open_bookings_tree(); });
var $btnInput = this.$el.find('#pms-menu #bookings_search');
$btnInput.on('keypress', function(ev){
if (ev.keyCode === 13) {
self._open_bookings_tree();
}
});
$button.on('click', function(ev){ self._open_search_tree('book'); });
$button = this.$el.find('#pms-menu #btn_action_checkins');
$button.on('click', function(ev){ self._open_search_tree('checkin'); });
$button = this.$el.find('#pms-menu #btn_action_invoices');
$button.on('click', function(ev){ self._open_search_tree('invoice'); });
$button = this.$el.find('#pms-menu #btn_action_folios');
$button.on('click', function(ev){ self._open_search_tree('folio'); });
// $button = this.$el.find('#pms-menu #bookings_search');
// $button.on('keypress', function(ev){
// if (ev.keyCode === 13) {
// self._open_bookings_tree();
// }
// });
this.$el.find("button[data-action]").on('click', function(ev){
self.do_action(this.dataset.action);
@@ -205,7 +190,7 @@ var HotelCalendarView = AbstractRenderer.extend({
},
loadViewFilters: function(resultsHotelRoomType, resultsHotelFloor, resultsHotelRoomAmenities, resultsHotelVirtualRooms) {
var $list = this.$el.find('#pms-search #type_list');
var $list = this.$el.find('#pms-menu #type_list');
$list.html('');
resultsHotelRoomType.forEach(function(item, index){
$list.append(`<option value="${item.id}">${item.name}</option>`);
@@ -218,7 +203,7 @@ var HotelCalendarView = AbstractRenderer.extend({
}.bind(this));
// Get Floors
$list = this.$el.find('#pms-search #floor_list');
$list = this.$el.find('#pms-menu #floor_list');
$list.html('');
resultsHotelFloor.forEach(function(item, index){
$list.append(`<option value="${item.id}">${item.name}</option>`);
@@ -229,7 +214,7 @@ var HotelCalendarView = AbstractRenderer.extend({
}.bind(this));
// Get Amenities
$list = this.$el.find('#pms-search #amenities_list');
$list = this.$el.find('#pms-menu #amenities_list');
$list.html('');
resultsHotelRoomAmenities.forEach(function(item, index){
$list.append(`<option value="${item.id}">${item.name}</option>`);
@@ -240,7 +225,7 @@ var HotelCalendarView = AbstractRenderer.extend({
}.bind(this));
// Get Virtual Rooms
$list = this.$el.find('#pms-search #virtual_list');
$list = this.$el.find('#pms-menu #virtual_list');
$list.html('');
resultsHotelVirtualRooms.forEach(function(item, index){
$list.append(`<option value="${item.id}">${item.name}</option>`);
@@ -252,7 +237,7 @@ var HotelCalendarView = AbstractRenderer.extend({
},
toggle_pms_search: function() {
var $pms_search = this.$el.find('#pms-search');
var $pms_search = this.$el.find('#pms-menu');
if ($pms_search.position().top < 0)
{
var $navbar = $('.navbar');
@@ -269,7 +254,7 @@ var HotelCalendarView = AbstractRenderer.extend({
}
},
_generate_bookings_domain: function(tsearch) {
_generate_search_domain: function(tsearch) {
var domain = [];
domain.push('|', '|', '|', '|',
['partner_id.name', 'ilike', tsearch],
@@ -280,22 +265,41 @@ var HotelCalendarView = AbstractRenderer.extend({
return domain;
},
_open_bookings_tree: function() {
_open_search_tree: function(type) {
var $elm = this.$el.find('#pms-menu #bookings_search');
var searchQuery = $elm.val();
var domain = false;
if (searchQuery) {
domain = this._generate_bookings_domain(searchQuery);
domain = this._generate_search_domain(searchQuery);
} else {
domain = [];
}
var model = '';
var title = '';
if (type === 'book' || type === 'book') {
model = 'hotel.reservation';
title = _t('Reservations');
} else if (type === 'checkin') {
model = 'hotel.reservation';
title = _t('Checkins');
domain.splice(0, 0, ['checkin', '=', moment().format(HotelConstants.ODOO_DATETIME_MOMENT_FORMAT)]);
} else if (type === 'invoice') {
model = 'sale.order';
title = _t('Invoices');
} else if (type === 'folio') {
model = 'hotel.folio'
title = _t('Folios');
}
this.do_action({
type: 'ir.actions.act_window',
view_mode: 'form',
view_type: 'tree,form',
res_model: 'hotel.reservation',
res_model: model,
views: [[false, 'list'], [false, 'form']],
domain: domain,
name: searchQuery?'Reservations for ' + searchQuery:'All Reservations'
name: searchQuery?`${title} for ${searchQuery}`:`All ${title}`
});
$elm.val('');

View File

@@ -12,6 +12,7 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
var MultiCalendar = Widget.extend({
_calendars: [],
_calendar_records: [],
_active_index: -1,
_events: {},
_tabs: [],
@@ -37,6 +38,10 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
return this._calendars[index-1];
},
get_calendar_record: function(index) {
return this._calendar_records[index-1];
},
get_tab: function(index) {
return this._tabs[index];
},
@@ -53,6 +58,23 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
return this._tabs[this._active_index];
},
update_active_tab_name: function(name) {
var [$tab, $panel] = this.get_tab(this.get_active_index());
$tab.text(name);
},
get_active_filters: function() {
var calendar = this.get_active_calendar();
var domain = calendar.getDomain(HotelCalendar.DOMAIN.ROOMS);
var filters = {};
for (var rule of domain) {
filters[rule[0]] = rule[2];
}
return filters;
},
recalculate_reservation_positions: function() {
var active_calendar = this.get_active_calendar();
if (active_calendar) {
@@ -189,8 +211,8 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
}
},
create_calendar: function(name) {
var [$tab, $panel] = this._create_tab(name, `calendar-pane-${name}`);
create_calendar: function(calendar_record) {
var [$tab, $panel] = this._create_tab(calendar_record['name'], `calendar-pane-${calendar_record['name']}`);
var calendar = new HotelCalendar(
$panel[0],
this._options,
@@ -201,6 +223,7 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
this._assign_extra_info(calendar);
calendar.setReservations(this._dataset['reservations']);
this._calendars.push(calendar);
this._calendar_records.push(calendar_record);
return this._calendars.length-1;
},
@@ -256,7 +279,15 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) {
var [$tab, $panel] = this._create_tab('+', 'default', {class: 'multi-calendar-tab-plus'});
$tab.on('shown.bs.tab', function(ev){
ev.preventDefault();
var new_calendar_id = self.create_calendar(`Calendar #${self._calendars.length}`);
var calendar_record = {
id: false,
name: `Calendar #${self._calendars.length}`,
segmentation_ids: [],
location_ids: [],
amenity_ids: [],
room_type_ids: []
};
var new_calendar_id = self.create_calendar(calendar_record);
self.set_active_calendar(new_calendar_id);
});
$('<p/>', {

View File

@@ -53,6 +53,7 @@
#hcal_widget {
max-height: 100%;
background-color: white;
}
#cal-pag-prev-plus, #cal-pag-prev, #cal-pag-selector, #cal-pag-next, #cal-pag-next-plus {
@@ -105,17 +106,22 @@
color: #654a37;
}
.btn-hcal.hcal-cell-end-week {
background-color: #0D5A8F;
background-color: #CBE5F8;
}
.btn-hcal-3d {
color: white;
background-color: #7c7bad;
border: 1px solid #cfcfdd;
border: 1px solid #eaeaea;
border-top-width: 0;
border-bottom-width: 0;
/*border-color: white black black white !important;*/
}
.btn-hcal-flat {
background-color: #cfcfdd;
border: 1px solid #cfcfdd;
background-color: white;
border: 1px solid #eaeaea;
}
.btn-hcal-left {
background-color: white;
border: 1px solid #eaeaea;
border-left-width: 0;
}
.hcal-warn-ob-indicator {
@@ -168,7 +174,7 @@
.hcal-table-day {
height: 100%;
border-collapse: collapse !important;
border: 0 dotted #cfcfcf;
border: 0 dotted #eaeaea;
border-width: 2px 0;
}
/*.hcal-table-day tr:first-child td{
@@ -189,17 +195,17 @@
font-size: 7px;
vertical-align: middle;
font-weight: bold;
border: 1px solid #cecece !important;
border: 1px solid #eaeaea !important;
}
.hcal-table-day td:hover:not(.hcal-cell-highlight):not(.hcal-cell-invalid) {
background-color: #FCFEE1 !important;
}
.hcal-cell-current-day {
background-color: #E0F8B0;
background-color: #FAFFD9;
}
.hcal-cell-end-week {
background-color: #E2EAF9;
background-color: #ECF3FF;
}
.hcal-cell-day-selector {
@@ -292,8 +298,8 @@
text-align: center;
/*background-color: #729fcf;*/
/*transform: skewX(-25deg);*/
border-radius: 5px;
border: 1px solid #3465a4;
/*border-radius: 5px;*/
border: 0 double #3465a4;
color: white;
white-space: nowrap;
overflow: hidden;
@@ -377,7 +383,7 @@
}
tr.hcal-row-room-type-group-overbooking-item td {
background-color: #c78585;
background-color: #fcebeb;
}
.hcal-cell-month-day {
@@ -477,23 +483,6 @@ td.hcal-cell-month-day-occupied {
text-align: center;
}
button#btn_action_bookings {
margin-bottom: -1px !important;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
input#bookings_search {
border-top-left-radius: 0;
border-top-right-radius: 0;
margin-bottom: 0.2em;
}
.multi-calendar-tab-plus {
background-color: darkgray;
font-weight: bold;
color: white;
}
.noselect {
-webkit-touch-callout: none; /* iOS Safari */
-webkit-user-select: none; /* Safari */

View File

@@ -56,6 +56,8 @@ function HotelCalendar(/*String*/querySelector, /*Dictionary*/options, /*List*/p
showNumRooms: 0,
paginatorStepsMin: 1,
paginatorStepsMax: 15,
showOverbookings: false,
showCancelled: false,
}, options);
this.options.startDate = this.options.startDate.clone();
this.options.startDate.subtract('1', 'd');
@@ -134,6 +136,14 @@ HotelCalendar.prototype = {
return this.options;
},
toggleOverbookingsVisibility: function(/*Bool*/show) {
this.options.showOverbookings = !this.options.showOverbookings;
},
toggleCancelledVisibility: function(/*Bool*/show) {
this.options.showCancelled = !this.options.showCancelled;
},
setSwapMode: function(/*Int*/mode) {
if (mode !== this._modeSwap) {
this._modeSwap = mode;
@@ -172,7 +182,7 @@ HotelCalendar.prototype = {
},
getDomain: function(/*Int*/section) {
return this._domains[section];
return this._domains[section] || [];
},
//==== RESERVATIONS
@@ -216,8 +226,15 @@ HotelCalendar.prototype = {
// Merge
var uzr = [];
for (var r of reservations) {
r = r.clone(); // HOT-FIX: Multi-Calendar Support
if (!this.options.showOverbookings && r.overbooking) {
var rindex = !forced?_.findKey(this._reservations, {'id': r.id}):false;
if (rindex) {
this.removeReservation(this._reservations[rindex]);
}
continue;
}
r = r.clone(); // HOT-FIX: Multi-Calendar Support
r.room = this.getRoom(r.room_id, r.overbooking, r.id);
// need create a overbooking row?
if (!r.room && r.overbooking) {
@@ -399,7 +416,7 @@ HotelCalendar.prototype = {
// Search End Cell
if (reservation.endDate.clone().local().isSameOrBefore(this._endDate, 'd')) {
reservation._drawModes[1] = 'hard-end';
limits.right = this.getCell(reservation.endDate.clone().local(),
limits.right = this.getCell(reservation.endDate.clone().subtract(1, 'd').local(),
reservation.room,
bedNum);
}
@@ -697,8 +714,10 @@ HotelCalendar.prototype = {
for (var i=start_index; i<this.options.rooms.length; i++) {
var reservs = this.getReservationsByRoom(this.options.rooms[i], true);
for (var reserv of reservs) {
var top = parseInt(reserv._html.style.top, 10);
reserv._html.style.top = (cheight === 0)?'0':`${top + cheight}px`;
if (reserv && reserv._html) {
var top = parseInt(reserv._html.style.top, 10);
reserv._html.style.top = (cheight === 0)?'0':`${top + cheight}px`;
}
}
}
@@ -1025,7 +1044,7 @@ HotelCalendar.prototype = {
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-3d');
cell.dataset.hcalDate = dd_local.format(HotelCalendar.DATE_FORMAT_SHORT_);
cell.innerHTML = `${dd_local.format('D')}<br/>${dd_local.format('ddd')}`;
cell.innerHTML = `${dd_local.format('ddd')}<br/>${dd_local.format('D')}`;
cell.setAttribute('title', dd_local.format('dddd'))
var day = +dd_local.format('D');
if (day == 1) {
@@ -1076,7 +1095,7 @@ HotelCalendar.prototype = {
cell.textContent = itemRoom.number;
cell.classList.add('hcal-cell-room-type-group-item');
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-3d');
cell.classList.add('btn-hcal-left');
cell.setAttribute('colspan', '2');
cell = row.insertCell();
cell.textContent = itemRoom.type;
@@ -1164,7 +1183,7 @@ HotelCalendar.prototype = {
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-3d');
cell.dataset.hcalDate = dd_local.format(HotelCalendar.DATE_FORMAT_SHORT_);
cell.innerHTML = `${dd_local.format('D')}<br/>${dd_local.format('ddd')}`;
cell.innerHTML = `${dd_local.format('ddd')}<br/>${dd_local.format('D')}`;
cell.setAttribute('title', dd_local.format("dddd"))
var day = +dd_local.format("D");
if (day == 1) {
@@ -1194,7 +1213,7 @@ HotelCalendar.prototype = {
cell.textContent = rt;
cell.classList.add('hcal-cell-detail-room-free-type-group-item');
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-flat');
cell.classList.add('btn-hcal-left');
cell.setAttribute("colspan", "3");
for (var i=0; i<=this.options.days; i++) {
var dd = this.options.startDate.clone().local().startOf('day').add(i,'d').utc();
@@ -1226,7 +1245,7 @@ HotelCalendar.prototype = {
cell.textContent = 'FREE TOTAL';
cell.classList.add('hcal-cell-detail-room-free-total-group-item');
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-flat');
cell.classList.add('btn-hcal-left');
cell.setAttribute("colspan", "3");
for (var i=0; i<=this.options.days; i++) {
var dd = this.options.startDate.clone().local().startOf('day').add(i,'d').utc();
@@ -1255,7 +1274,7 @@ HotelCalendar.prototype = {
cell.textContent = '% OCCUP.';
cell.classList.add('hcal-cell-detail-room-perc-occup-group-item');
cell.classList.add('btn-hcal');
cell.classList.add('btn-hcal-flat');
cell.classList.add('btn-hcal-left');
cell.setAttribute("colspan", "3");
for (var i=0; i<=this.options.days; i++) {
var dd = this.options.startDate.clone().local().startOf('day').add(i,'d').utc();
@@ -1293,7 +1312,7 @@ HotelCalendar.prototype = {
cell = row.insertCell();
var span = document.createElement('span');
cell.title = cell.textContent = listitem.title + ' ' + this.options.currencySymbol;
cell.classList.add('hcal-cell-detail-room-group-item', 'btn-hcal', 'btn-hcal-flat');
cell.classList.add('hcal-cell-detail-room-group-item', 'btn-hcal', 'btn-hcal-left');
cell.dataset.currencySymbol = this.options.currencySymbol;
cell.setAttribute("colspan", "3");
for (var i=0; i<=$this.options.days; i++) {
@@ -1535,6 +1554,7 @@ HotelCalendar.prototype = {
var limitLeftDateMoment = HotelCalendar.toMoment(limitLeftDate);
var limitRightDateMoment = HotelCalendar.toMoment(limitRightDate);
var diff_date = this.getDateDiffDays(limitLeftDateMoment, limitRightDateMoment);
if (reserv._drawModes[1] === 'hard-end') { --diff_date; }
var date = limitLeftDateMoment.clone().startOf('day');
var selector = [];
for (var i=0; i<=diff_date; i++) {
@@ -1604,7 +1624,7 @@ HotelCalendar.prototype = {
// FIXME: Normalize data calendar (gmt) vs extra info (utc)
var date_cell = HotelCalendar.toMoment(this.etable.querySelector(`#${c.dataset.hcalParentCell}`).dataset.hcalDate);
var room_price = this.getRoomPrice(parentRow.dataset.hcalRoomObjId, date_cell);
if (c === cells[0] || !date_cell.isSame(limitRightDate, 'day')) {
if (c === cells[0]) {
c.textContent = room_price + ' ' + this.options.currencySymbol;
if (!room.shared && c.dataset.hcalBedNum > limits.left.dataset.hcalBedNum) {
c.style.color = 'lightgray';
@@ -1683,39 +1703,28 @@ HotelCalendar.prototype = {
var divHeight = (boundsEnd.bottom-etableOffset.top)-(boundsInit.top-etableOffset.top);
reserv._html.style.height = `${divHeight}px`;
reserv._html.style.lineHeight = `${divHeight}px`;
var fontHeight = divHeight/1.3;
var fontHeight = divHeight/1.2;
if (fontHeight > 16) {
fontHeight = 16;
}
reserv._html.style.fontSize = `${fontHeight}px`;
var clearBorderLeft = function(/*HTMLObject*/elm) {
elm.style.borderLeftWidth = '0';
elm.style.borderTopLeftRadius = '0';
elm.style.borderBottomLeftRadius = '0';
elm.style.borderLeftWidth = '3px';
};
var clearBorderRight = function(/*HTMLObject*/elm) {
elm.style.borderRightWidth = '0';
elm.style.borderTopRightRadius = '0';
elm.style.borderBottomRightRadius = '0';
elm.style.borderRightWidth = '3px';
};
reserv._html.style.left = `${boundsInit.left-etableOffset.left}px`;
reserv._html.style.width = `${(boundsEnd.left-boundsInit.left)+boundsEnd.width}px`;
if (reserv._drawModes[0] === 'soft-start' && reserv._drawModes[1] === 'soft-end') {
clearBorderLeft(reserv._html);
clearBorderRight(reserv._html);
reserv._html.style.left = `${boundsInit.left-etableOffset.left}px`;
reserv._html.style.width = `${(boundsEnd.left-boundsInit.left)+boundsEnd.width}px`;
} else if (reserv._drawModes[0] === 'soft-start') {
clearBorderLeft(reserv._html);
reserv._html.style.left = `${boundsInit.left-etableOffset.left}px`;
reserv._html.style.width = `${(boundsEnd.left-boundsInit.left)+boundsEnd.width/2.0}px`;
} else if (reserv._drawModes[1] === 'soft-end') {
clearBorderRight(reserv._html);
reserv._html.style.left = `${boundsInit.left-etableOffset.left+boundsInit.width/2.0}px`;
reserv._html.style.width = `${(boundsEnd.left-boundsInit.left)+boundsEnd.width}px`;
} else {
reserv._html.style.left = `${(boundsInit.left-etableOffset.left)+boundsEnd.width/2.0}px`;
reserv._html.style.width = `${(boundsEnd.left-boundsInit.left)}px`;
}
}
},
@@ -2163,7 +2172,9 @@ HotelCalendar.prototype = {
//break;
} else { return false; }
} else if (compMode === 'some') {
if ((obj[fieldName] && typeof obj[fieldName] === 'object' && _.some(f[2], function(item) { return obj[fieldName].indexOf(item) !== -1; })) ||
if ((fieldName in obj && obj[fieldName] in f[2]) ||
f[2].indexOf(userDataValue) != -1 ||
(obj[fieldName] && typeof obj[fieldName] === 'object' && _.some(f[2], function(item) { return obj[fieldName].indexOf(item) !== -1; })) ||
(userDataValue && typeof userDataValue === 'object' && userDataValue.length && _.some(f[2], function(item) { return userDataValue.indexOf(item) !== -1; }))) {
founded = true;
//break;
@@ -2311,7 +2322,6 @@ HotelCalendar.prototype = {
_onCellMouseUp: function(ev) {
if (this._cellSelection.start &&
this._cellSelection.start != ev.target &&
this._cellSelection.start.dataset.hcalParentRow === ev.target.dataset.hcalParentRow) {
this._cellSelection.end = ev.target;
@@ -2362,12 +2372,12 @@ HotelCalendar.prototype = {
return true;
}
if (!date_cell.isAfter(reserv.startDate, 'd')) {
date_cell = reserv.startDate.clone().startOf('day').add(1, 'd');
date_cell = reserv.startDate.clone().startOf('day');
}
if (!this.reservationAction.oldReservationObj) {
this.reservationAction.oldReservationObj = reserv.clone();
}
reserv.endDate.set({'date': date_cell.date(), 'month': date_cell.month(), 'year': date_cell.year()});
reserv.endDate.set({'date': date_cell.date(), 'month': date_cell.month(), 'year': date_cell.year()}).add(1, 'd');
this.reservationAction.newReservationObj = reserv;
needUpdate = true;
} else if (this.reservationAction.action == HotelCalendar.ACTION.MOVE_LEFT) {
@@ -2624,7 +2634,7 @@ HotelCalendar.prototype = {
if (reverse) {
value = max-value;
}
rgb = this._hslToRgb(((max-value)*offset)/max, 1.0, 0.5);
rgb = this._hslToRgb(((max-value)*offset)/max, 1.0, 0.8);
if (!strmode) {
return rgb;
}

View File

@@ -3,88 +3,139 @@
<t t-name="hotel_calendar.HotelCalendarView">
<div class="col-xs-12 col-md-12 nopadding">
<div class="col-lg-1 hidden-xs hidden-sm nopadding" id="pms-menu">
<button class="btn btn-default col-xs-12 col-md-12" id="btn_action_checkout" data-action="hotel_calendar.hotel_reservation_action_checkout">
<div class="ninfo"><span class="badge badge-danger">0</span></div>
CHECK-OUT
</button>
<button class="btn btn-default col-xs-12 col-md-12" id="btn_action_checkin" data-action="hotel_calendar.hotel_reservation_action_checkin">
<div class="ninfo"><span class="badge badge-danger">0</span></div>
CHECK-IN
</button>
<button class="btn btn-default col-xs-12 col-md-12" id="btn_action_bookings">
<!--div class="ninfo"><span class="badge badge-danger">0</span></div-->
BOOKS<br/>
</button>
<input type="edit" id="bookings_search" placeholder="Search..." style="width:100%; border:1px solid lightgray;" />
<button class="btn btn-default col-xs-12 col-md-12" id="btn_action_control" data-action="hotel.open_wizard_reservations">
WIZARD
</button>
<button class="btn btn-default col-xs-12 col-md-12" id="btn_swap">
<div class="ninfo"><span class="badge badge-danger">0</span></div>
<span class="ntext">START SWAP</span>
</button>
<!--button class="btn btn-default col-xs-12 col-md-12" id="btn_action_refresh">
<i class="fa fa-4x fa-refresh"> </i>
</button-->
</div>
<div class="col-xs-12 col-sm-12 col-md-11 nopadding">
<div class="col-xs-11 col-md-11 nopadding" id="pms-search">
<table class="col-xs-12 col-md-12 nopadding" id="pms-search-table">
<tbody>
<tr>
<td class="col-xs-3 col-md-4">
<div class="col-xs-12 col-md-12 text-left">
<label for="type_list">SEGMENTATION:</label>
<select class="form-control" id="type_list" multiple="multiple"/>
</div>
<div class="col-xs-12 col-md-12 text-left">
<label for="floor_list">LOCATION:</label>
<select class="list form-control" id="floor_list" multiple="multiple"/>
</div>
</td>
<td class="col-xs-3 col-md-4">
<div class="col-xs-12 col-md-12 text-left">
<label for="amenities_list">AMENITIES:</label>
<select class="list form-control" id="amenities_list" multiple="multiple"/>
</div>
<div class="col-xs-12 col-md-12 text-left">
<label for="virtual_list">VIRTUAL:</label>
<select class="list form-control" id="virtual_list" multiple="multiple"/>
</div>
</td>
<td class="col-xs-6 col-md-4">
<div class="col-xs-12 col-md-12">
<table style="margin: 0 auto">
<tbody>
<tr>
<td>
<label for="date_begin">FROM</label>
<div class="input-group date" id="date_begin">
<input type="text" class="o_datepicker_input form-control" name="date_begin" required="required"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
</td>
<td>
<label for="date_end">TO</label>
<div class="input-group date" id="date_end">
<input type="text" class="o_datepicker_input form-control" name="date_end" required="required"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</td>
</tr>
</tbody>
</table>
<div class="col-lg-2 hidden-xs hidden-sm" id="pms-menu">
<div class="col-xs-12 col-md-12 nopadding menu-date-box">
<div class="input-group date" id="date_begin">
<input type="text" class="o_datepicker_input form-control" name="date_begin" required="required"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
<div class="input-group date" id="date_end">
<input type="text" class="o_datepicker_input form-control" name="date_end" required="required"/>
<span class="input-group-addon">
<span class="fa fa-calendar"></span>
</span>
</div>
</div>
<div class="col-xs-12 col-md-12 nopadding menu-button-box">
<div class="col-xs-6 col-md-6" id="btn_action_checkout">
<button class="btn btn-default col-xs-12 col-md-12 button-box" data-action="hotel_calendar.hotel_reservation_action_checkout">
<i class="fa fa-fw o_button_icon fa-sign-out"> </i>
<div class="o_button_text">
<span class="ninfo">0</span><br/>
Checkouts
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_checkin">
<button class="btn btn-default col-xs-12 col-md-12 button-box" data-action="hotel_calendar.hotel_reservation_action_checkin">
<i class="fa fa-fw o_button_icon fa-sign-in"> </i>
<div class="o_button_text">
<span class="ninfo">0</span><br/>
Checkins
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_swap">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<div class='led led-disabled'></div>
<i class="fa fa-fw o_button_icon fa-retweet"> </i>
<div class="o_button_text">
<span class="ntext">Start Swap</span>
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_control">
<button class="btn btn-default col-xs-12 col-md-12 button-box" data-action="hotel.open_wizard_reservations">
<i class="fa fa-fw o_button_icon fa-magic"> </i>
<div class="o_button_text">
Wizard
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_overbooking">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<div class='led led-disabled'></div>
<i class="fa fa-fw o_button_icon fa-clock-o"> </i>
<div class="o_button_text">
<span class="ninfo">0</span><br/>
Overbooking
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_cancelled">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<div class='led led-disabled'></div>
<i class="fa fa-fw o_button_icon fa-calendar-times-o"> </i>
<div class="o_button_text">
Cancelled
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_divide">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<div class='led led-disabled'></div>
<i class="fa fa-fw o_button_icon fa-scissors"> </i>
<div class="o_button_text">
Divide
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_action_unify">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<div class='led led-disabled'></div>
<i class="fa fa-fw o_button_icon fa-compress"> </i>
<div class="o_button_text">
Unify
</div>
</button>
</div>
</div>
<div class="col-xs-12 col-md-12 nopadding menu-search-box">
<div class="input-group">
<input type="edit" id="bookings_search" placeholder="Name, Mail, Vat, Book..." class="form-control extra-search" />
<span class="input-group-addon bg-primary">
<span class="fa fa-search"></span>
</span>
</div>
<button class="btn btn-primary col-xs-6 col-md-6" id="btn_action_bookings">
Books
</button>
<button class="btn btn-primary col-xs-6 col-md-6" id="btn_action_checkins">
Checkins
</button>
<button class="btn btn-primary col-xs-6 col-md-6" id="btn_action_invoices">
Invoices
</button>
<button class="btn btn-primary col-xs-6 col-md-6" id="btn_action_folios">
Folios
</button>
</div>
<div class="col-xs-12 col-md-12 nopadding menu-filter-box">
<h4>Filters</h4>
<select class="form-control" id="type_list" placeholder="Select Segmentation..." multiple="multiple"/>
<select class="list form-control" id="floor_list" placeholder="Select Location..." multiple="multiple"/>
<select class="list form-control" id="amenities_list" placeholder="Select Amenities..." multiple="multiple"/>
<select class="list form-control" id="virtual_list" placeholder="Select Type..." multiple="multiple"/>
<div class="filter-record col-xs-12 col-md-12" style="padding:4px">
<div class="col-xs-8 col-md-8 nopadding">
<input type="edit" id="calendar_name" class="form-control" />
</div>
<div class="col-xs-2 col-md-2 nopadding">
<button class="btn btn-primary col-xs-12 col-md-12" id="btn_save_calendar_record">
<i class="fa fa-fw fa-save"> </i>
</button>
</div>
<div class="col-xs-2 col-md-2 nopadding">
<button class="btn btn-primary col-xs-12 col-md-12" id="btn_reload_calendar_filters">
<i class="fa fa-fw fa-refresh"> </i>
</button>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-sm-12 col-md-10 nopadding">
<div id="hcal_widget" class="col-xs-12 col-md-12 nopadding">
<div id="hcal_load">
<span>

View File

@@ -4,7 +4,7 @@
* Aloxa Solucions S.L. <info@aloxa.eu>
* Alexandre Díaz <alex@aloxa.eu>
*/
/** ANIMATIONS **/
@keyframes channel-manager-changes {
0% {
@@ -34,17 +34,11 @@
color: black;
}
}
#pms-menu #btn_channel_manager_request.incoming i {
animation-name: channel-manager-changes;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
}
#pms-menu #btn_channel_manager_request.incoming span {
animation-name: channel-manager-changes-text;
animation-duration: 2s;
animation-iteration-count: infinite;
animation-direction: alternate;
}

View File

@@ -10,26 +10,22 @@ odoo.define('hotel_calendar_channel_connector.PMSHotelCalendarRendererChannelCon
update_buttons_counter_channel_connector: function (nreservations, nissues) {
// Cloud Reservations
var $button = this.$el.find('#btn_channel_manager_request');
var $text = this.$el.find('#btn_channel_manager_request .cloud-text');
if (nreservations > 0) {
$button.addClass('incoming');
$text.parent().parent().addClass('button-highlight');
$text.parent().addClass('incoming');
$text.text(nreservations);
$text.show();
} else {
$button.removeClass('incoming');
$text.hide();
$text.parent().removeClass('incoming');
}
// Issues
var $ninfo = this.$el.find('#pms-menu #btn_action_issues div.ninfo');
var $badge_issues = $ninfo.find('.badge');
if (nissues > 0) {
$badge_issues.text(nissues);
$badge_issues.parent().show();
$ninfo.show();
$ninfo.text(nissues);
if (nissues) {
$ninfo.parent().parent().addClass('button-highlight');
} else {
$ninfo.hide();
$ninfo.parent().parent().removeClass('button-highlight');
}
},

View File

@@ -2,19 +2,25 @@
<templates xml:space="preserve">
<t t-extend="hotel_calendar.HotelCalendarView">
<t t-jquery="button#btn_action_checkout" t-operation="before">
<button class="btn col-xs-12 col-lg-12" id="btn_channel_manager_request">
<div class="fa-stack fa-2x">
<i class="fa fa-cloud fa-stack-2x"> </i>
<span class="fa-stack-1x cloud-text">0</span>
</div>
</button>
</t>
<t t-jquery="input#bookings_search" t-operation="after">
<button class="btn btn-default col-xs-12 col-lg-12" id="btn_action_issues" data-action="hotel_calendar_channel_connector.calendar_channel_connector_issues_action">
<div class="ninfo"><span class="badge badge-danger">0</span></div>
ISSUES
</button>
<t t-jquery="div#btn_action_checkin" t-operation="after">
<div class="col-xs-6 col-md-6" id="btn_action_issues">
<button class="btn btn-default col-xs-12 col-md-12 button-box" data-action="hotel_calendar_channel_connector.calendar_channel_connector_issues_action">
<i class="fa fa-fw o_button_icon fa-exclamation-circle"> </i>
<div class="o_button_text">
<span class="ninfo">0</span><br/>
Issues
</div>
</button>
</div>
<div class="col-xs-6 col-md-6" id="btn_channel_manager_request">
<button class="btn btn-default col-xs-12 col-md-12 button-box">
<i class="fa fa-fw o_button_icon fa-cloud"></i>
<div class="o_button_text">
<span class="cloud-text">0</span><br/>
To Assign
</div>
</button>
</div>
</t>
</t>