diff --git a/hotel_calendar/models/inherited_hotel_reservation.py b/hotel_calendar/models/inherited_hotel_reservation.py index 67a79f5cd..65217f47a 100644 --- a/hotel_calendar/models/inherited_hotel_reservation.py +++ b/hotel_calendar/models/inherited_hotel_reservation.py @@ -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 diff --git a/hotel_calendar/static/src/css/view.css b/hotel_calendar/static/src/css/view.css index cd1c21ffe..e81624b08 100644 --- a/hotel_calendar/static/src/css/view.css +++ b/hotel_calendar/static/src/css/view.css @@ -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; +} diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js index 7735bf77e..4f4077ecd 100644 --- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js +++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_controller.js @@ -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() { diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js index 095d4daf3..13fcceb19 100644 --- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js +++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_model.js @@ -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', diff --git a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js index 081950d49..1b1e13d7d 100644 --- a/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js +++ b/hotel_calendar/static/src/js/views/calendar/hotel_calendar_renderer.js @@ -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(``); @@ -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(``); @@ -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(``); @@ -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(``); @@ -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(''); diff --git a/hotel_calendar/static/src/js/widgets/MultiCalendar.js b/hotel_calendar/static/src/js/widgets/MultiCalendar.js index 6ef910273..c46faacd3 100644 --- a/hotel_calendar/static/src/js/widgets/MultiCalendar.js +++ b/hotel_calendar/static/src/js/widgets/MultiCalendar.js @@ -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); }); $('
', { diff --git a/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css b/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css index d25a9e2cf..ed453617b 100644 --- a/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css +++ b/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css @@ -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 */ diff --git a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js index 3a9a6d731..0c5b2ea83 100644 --- a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js +++ b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js @@ -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|
-
-
-
-
-
-
-
-
- |
-
-
-
-
-
-
-
-
-
- |
-
-
-
-
|
-