diff --git a/hotel/data/hotel_demo.xml b/hotel/data/hotel_demo.xml index 50be034ab..e6b6694e5 100644 --- a/hotel/data/hotel_demo.xml +++ b/hotel/data/hotel_demo.xml @@ -193,7 +193,7 @@ False 1 True - True + True @@ -206,7 +206,7 @@ - Menú A + Lunch 15.0 service False @@ -215,7 +215,7 @@ - Menú B + Dinner 20.0 service False @@ -224,8 +224,8 @@ - Menú C - 25.0 + Free Bar + 40.0 service False True @@ -249,7 +249,7 @@ eval="[(5, 0), (0, 0, { 'product_id': ref('hotel_service_0'), 'amount': 3}), - (0, 0, {'product_id': ref('hotel_service_4'), + (0, 0, {'product_id': ref('hotel_service_5'), 'amount': 8}) ]"/> fixed @@ -271,7 +271,7 @@ - + diff --git a/hotel/models/inherited_product_template.py b/hotel/models/inherited_product_template.py index 5a7ba560d..ce70952a1 100644 --- a/hotel/models/inherited_product_template.py +++ b/hotel/models/inherited_product_template.py @@ -11,5 +11,5 @@ class ProductTemplate(models.Model): per_person = fields.Boolean('Unit increment per person') daily_limit = fields.Integer('Daily limit') is_extra_bed = fields.Boolean('Is extra bed', default=False) - is_popoverable = fields.Boolean('Show in Popover', default=False, - help='Specifies if the product is shown in the popover information.') + show_in_calendar = fields.Boolean('Show in Calendar', default=False, + help='Specifies if the product is shown in the calendar information.') diff --git a/hotel/views/inherited_product_template_views.xml b/hotel/views/inherited_product_template_views.xml index c4233cbc7..2b3a54f1f 100644 --- a/hotel/views/inherited_product_template_views.xml +++ b/hotel/views/inherited_product_template_views.xml @@ -12,7 +12,7 @@ - + diff --git a/hotel_calendar/models/bus_hotel_calendar.py b/hotel_calendar/models/bus_hotel_calendar.py index 4c4b809d2..e81ac1385 100644 --- a/hotel_calendar/models/bus_hotel_calendar.py +++ b/hotel_calendar/models/bus_hotel_calendar.py @@ -52,7 +52,7 @@ class BusHotelCalendar(models.TransientModel): 'real_dates': vals['real_dates'], }, 'tooltip': { - 'folio_name': vals['folio_id'], + 'folio_name': vals['folio_name'], 'name': vals['partner_name'], 'phone': vals['partner_phone'], 'email': vals['partner_email'], @@ -63,9 +63,9 @@ class BusHotelCalendar(models.TransientModel): 'checkout': vals['checkout'], 'arrival_hour': vals['arrival_hour'], 'departure_hour': vals['departure_hour'], - 'amount_total': vals['amount_total'], + 'price_room_services_set': vals['price_room_services_set'], + 'invoices_paid': vals['invoices_paid'], 'pending_amount': vals['pending_amount'], - 'amount_paid': vals['amount_paid'], 'type': vals['reservation_type'], 'closure_reason': vals['closure_reason'], 'out_service_description': vals['out_service_description'], diff --git a/hotel_calendar/models/inherited_hotel_reservation.py b/hotel_calendar/models/inherited_hotel_reservation.py index 0bea4cc0b..5c145ec38 100644 --- a/hotel_calendar/models/inherited_hotel_reservation.py +++ b/hotel_calendar/models/inherited_hotel_reservation.py @@ -95,7 +95,7 @@ class HotelReservation(models.Model): 'real_dates': [reserv['real_checkin'], reserv['real_checkout']]}) json_reservation_tooltips.update({ reserv['id']: { - 'folio_name': reserv['folio_id'], + 'folio_name': reserv['folio_name'], 'name': _('Out of service') if reserv['reservation_type'] == 'out' else reserv['partner_name'], @@ -109,9 +109,9 @@ class HotelReservation(models.Model): 'checkout': reserv['checkout'], 'arrival_hour': reserv['arrival_hour'], 'departure_hour': reserv['departure_hour'], - 'amount_total': reserv['amount_total'], + 'price_room_services_set': reserv['price_room_services_set'], + 'invoices_paid': reserv['invoices_paid'], 'pending_amount': reserv['pending_amount'], - 'amount_paid': reserv['amount_total'] - (reserv['pending_amount'] or 0.0), 'type': reserv['reservation_type'] or 'normal', 'closure_reason': reserv['closure_reason'], 'out_service_description': reserv['out_service_description'] @@ -119,8 +119,7 @@ class HotelReservation(models.Model): 'splitted': reserv['splitted'], 'channel_type': reserv['channel_type'], 'real_dates': [reserv['real_checkin'], reserv['real_checkout']], - # TODO: Add Board Services and Extra Service as Cradle, Bed, ... - 'board_service_name': reserv['board_service_name'], + 'board_service_name': reserv['board_service_name'] or _('No board services'), 'services': reserv['services'], } }) @@ -190,14 +189,15 @@ class HotelReservation(models.Model): hr.id, hr.room_id, hr.adults, hr.children, hr.checkin, hr.checkout, hr.reserve_color, hr.reserve_color_text, hr.splitted, hr.parent_reservation, hr.overbooking, hr.state, hr.real_checkin, hr.real_checkout, hr.out_service_description, hr.arrival_hour, hr.departure_hour, hr.channel_type, + hr.price_room_services_set, - hf.id as folio_id, hf.name as folio_name, hf.reservation_type, hf.amount_total, hf.pending_amount, + hf.id as folio_id, hf.name as folio_name, hf.reservation_type, hf.invoices_paid, hf.pending_amount, rp.mobile, rp.phone, rp.email, rp.name as partner_name, pt.name as room_type, - array_agg(pt2.name) FILTER (WHERE pt2.is_popoverable = TRUE) as services, + array_agg(pt2.name) FILTER (WHERE pt2.show_in_calendar = TRUE) as services, rcr.name as closure_reason, @@ -393,6 +393,7 @@ class HotelReservation(models.Model): 'title': ntitle, 'room_id': self.room_id.id, 'reserv_id': self.id, + 'folio_name': self.folio_id.name, 'partner_name': (self.closure_reason_id.name or _('Out of service')) if self.reservation_type == 'out' else self.partner_id.name, 'adults': self.adults, @@ -415,18 +416,18 @@ class HotelReservation(models.Model): 'state': self.state, 'fix_days': self.splitted, 'overbooking': self.overbooking, - 'amount_total': self.folio_id.amount_total, + 'price_room_services_set': self.price_room_services_set, + 'invoices_paid': self.folio_id.invoices_paid, 'pending_amount': self.folio_id.pending_amount, - 'amount_paid': self.folio_id.amount_total - self.folio_id.pending_amount, 'reservation_type': self.reservation_type or 'normal', 'closure_reason': self.closure_reason_id.name, 'out_service_description': self.out_service_description or _('No reason given'), 'real_dates': [self.real_checkin, self.real_checkout], 'channel_type': self.channel_type, - 'board_service_name': self.board_service_room_id.hotel_board_service_id.name, + 'board_service_name': self.board_service_room_id.hotel_board_service_id.name or _('No board services'), 'services': [service.product_id.name for service in self.service_ids - if service.product_id.is_popoverable] or False, + if service.product_id.show_in_calendar] or False, } @api.multi diff --git a/hotel_calendar/static/src/css/view.css b/hotel_calendar/static/src/css/view.css index 9c99c8b43..6a5cf20c6 100644 --- a/hotel_calendar/static/src/css/view.css +++ b/hotel_calendar/static/src/css/view.css @@ -224,73 +224,118 @@ input#bookings_search { text-overflow: ellipsis; } -/** TOOLTIPS **/ +/** POPOVER **/ .popover-content { - font-family: Garuda, sans-serif; - font-size: 12px; - padding: 9px; + font-family: Garuda, sans-serif; + font-size: 12px; + padding: 0px; } -.popover h1, .h1, h2, .h2, h3, .h3 { - margin-top: 2px; - margin-bottom: 0px; +.popover .h3, .popover h3 { + margin-top: 2px; + margin-bottom: 2px; } .popover { - max-width: 550px; - border-radius: 0px; + max-width: 400px; + border-radius: 0px; + padding: 0px; } .popover .container { - max-width: 100%; + max-width: 100%; } .popover .container p { - margin-top: 3px; - margin-bottom: 0px; + margin-top: 2px; + margin-bottom: 0px; +} +.popover .container p.email { + word-wrap: break-word; +} +.popover .container p.board { + margin-top: 0px; } .popover header { - font-size: 1.3em; -} -.popover .fa-border { - padding: .25em; - border: solid 0.1em #777777; - border-radius: .2em; + font-size: 1.2em; } +.fa-2_5x { + font-size: 2.5em; +} .fa-text-inside { - font-family: Garuda, sans-serif; - font-size: 14px; + font-family: Garuda, sans-serif; + font-size: 12px; } -.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 { - padding-top: 3px; - padding-bottom: 3px; +.popover .col-sm-2, .popover .col-sm-4, .popover .col-sm-6, .popover .col-sm-12 { + padding-top: 3px; + padding-bottom: 3px; } +/* custom styles for popover info */ +.popover .circle { + height:35px; + min-width:35px; + line-height:35px; + border-radius:50px; + text-align:center; + color:#fff; + background:#777; + margin-right: .65em; + padding: 0 5px; +} + +.popover .bg-gray-lighter { + background-color: #ddd; + color: #777; +} +.popover .text-gray-dark { + color: #777; +} + + /* Spacing in Bootstrap v4.0 */ .mt-3 { - margin-top: 3px; + margin-top: 3px; +} +.mt-5 { + margin-top: 5px; } .mt-10 { - margin-top: 10px !important; + margin-top: 10px !important; +} +.my-10 { + margin-top: 10px !important; + margin-bottom: 10px !important; } .mt-25 { - margin-top: 25px; + margin-top: 25px; } .mr-5 { - margin-right: 5px; + margin-right: 5px; +} +.mx-15 { + margin-left: 15px; + margin-right: 15px; } .mx-25 { - margin-left: 25px; - margin-right: 25px; + margin-left: 25px; + margin-right: 25px; +} +.px-0 { + padding-left: 0px; + padding-right: 0px; } .py-5 { - padding-top: 5px; - padding-bottom: 5px; + padding-top: 5px; + padding-bottom: 5px; +} +.pb-3 { + padding-bottom: 3px; } .pb-10 { - padding-bottom: 10px; + padding-bottom: 10px; } - -@media (min-width:0px) and (max-width: 1600px) { - /* .text-hidden-xs { - visibility: hidden; - } */ +.pl-5 { + padding-left: 5px; +} +.pr-0 { + padding-right: 0px; } /* WARNING: The .row-eq-height class uses CSS3's flexbox layout mode, @@ -303,3 +348,44 @@ input#bookings_search { } /* TODO: Use Odoo Colours based on http://www.odoo.com/openerp_website/static/src/less/variables.less */ + +div.diagonal { + overflow: hidden; + background-color: #777; +} +.diagonal:before { + content: ""; + border-top: 700px solid #777; + border-right: 500px solid #ddd; + position: absolute; + left: 40%; + bottom: 0; +} + +div.triangle-right { + overflow: hidden; + color: white; + background-color: #7c7bad; +} +.triangle-right:before { + content: ""; + position: absolute; + border: 26px solid #ddd; + height: 0; + width: 100%; + left: 47%; + top: 0; + bottom: 0; + margin: auto; + border-left-color: transparent; +} + +div.on-top { + position: inherit; +} +div.pull-right-custom { + float: right !important; + margin-right: 15px; + color: #777; + text-align: right; +} \ No newline at end of file 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 d57898dff..ac8420448 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 @@ -420,7 +420,7 @@ var PMSCalendarController = AbstractController.extend({ type: 'ir.actions.act_window', res_model: 'hotel.folio', res_id: ev.data.folio_id, - views: [[false, 'form']] + views: [[false, 'form']], }); }); $reservationPopover.data('bs.popover').tip().find(".btn_popover_open_reservation").on('click', @@ -433,6 +433,57 @@ var PMSCalendarController = AbstractController.extend({ views: [[false, 'form']] }); }); + $reservationPopover.data('bs.popover').tip().find(".btn_popover_open_payment").on('click', + {reservation_id: ev.detail.reservationObj.id}, function(ev){ + _destroy_and_clear_popover_mark(); + var x = self._rpc({ + model: 'hotel.reservation', + method: 'action_pay_folio', + args: [ev.data.reservation_id], + }).then(function (result){ + return self.do_action({ + name: result.name, + view_type: result.view_type, + view_mode: result.view_mode, + type: result.type, + res_model: result.res_model, + views: [[result.view_id, 'form']], + context: result.context, + target: result.target, + }); + }); + }); + $reservationPopover.data('bs.popover').tip().find(".btn_popover_open_checkin").on('click', + {reservation_id: ev.detail.reservationObj.id}, function(ev){ + _destroy_and_clear_popover_mark(); + var x = self._rpc({ + model: 'hotel.reservation', + method: 'action_checks', + args: [ev.data.reservation_id], + }).then(function (result){ + return self.do_action({ + name: result.name, + view_type: result.view_type, + view_mode: result.view_mode, + type: result.type, + res_model: result.res_model, + views: [[false, 'form']], + domain: result.domain, + target: result.target, + }); + }); + }); + $reservationPopover.data('bs.popover').tip().find(".btn_popover_open_invoice").on('click', + {reservation_id: ev.detail.reservationObj.id}, function(ev){ + _destroy_and_clear_popover_mark(); + var x = self._rpc({ + model: 'hotel.reservation', + method: 'open_invoices_reservation', + args: [ev.data.reservation_id], + }).then(function (result){ + return self.do_action(result); + }); + }); $reservationPopover.data('bs.popover').tip().find(".btn_popover_close").on('click', function(ev){ _destroy_and_clear_popover_mark(); }); @@ -699,6 +750,10 @@ var PMSCalendarController = AbstractController.extend({ }).open(); }); + this._multi_calendar.on_calendar('hcalOnKeyPressed', function(ev){ + /* add actions */ + }); + this._multi_calendar.on_calendar('hcalOnDateChanged', function(ev){ var $dateTimePickerBegin = this.renderer.$el.find('#pms-menu #date_begin'); $dateTimePickerBegin.data("ignore_onchange", true); @@ -754,9 +809,9 @@ var PMSCalendarController = AbstractController.extend({ 'checkout_day_of_week': HotelCalendar.toMomentUTC(tp['real_dates'][1], '').format("dddd"), 'arrival_hour': tp['arrival_hour'], 'departure_hour': tp['departure_hour'], - 'amount_total': Number(tp['amount_total']).toLocaleString(), + 'price_room_services_set': Number(tp['price_room_services_set']).toLocaleString(), + 'invoices_paid': Number(tp['invoices_paid']).toLocaleString(), 'pending_amount': Number(tp['pending_amount']).toLocaleString(), - 'amount_paid': Number(tp['amount_paid']).toLocaleString(), 'reservation_type': tp['type'], 'closure_reason': tp['closure_reason'], 'out_service_description': tp['out_service_description'], diff --git a/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css b/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css index 0f9b6def8..4bd0fa220 100644 --- a/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css +++ b/hotel_calendar/static/src/lib/hcalendar/css/hcalendar.css @@ -464,7 +464,7 @@ td.hcal-cell-room-type-group-day { td.hcal-cell-room-type-group-item { text-align: center !important; vertical-align: middle; - font-size: x-small; + font-size: smaller; white-space: nowrap; text-overflow: ellipsis; } diff --git a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js index b23c39f3b..f57934073 100644 --- a/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js +++ b/hotel_calendar/static/src/lib/hcalendar/js/hcalendar.js @@ -761,13 +761,14 @@ HotelCalendar.prototype = { cell.classList.add('hcal-cell-room-type-group-item'); cell.classList.add('btn-hcal'); cell.classList.add('btn-hcal-3d'); - cell.setAttribute('colspan', '2'); + cell.setAttribute('colspan', '3'); + /* cell = row.insertCell(); cell.textContent = ex_room.type; cell.classList.add('hcal-cell-room-type-group-item'); cell.classList.add('btn-hcal'); cell.classList.add('btn-hcal-flat'); - + */ var now = moment(); for (var i=0; i<=this.options.days; i++) { var dd = this.options.startDate.clone().local().startOf('day').add(i,'d').utc(); @@ -1154,12 +1155,14 @@ HotelCalendar.prototype = { cell.classList.add('hcal-cell-room-type-group-item'); cell.classList.add('btn-hcal'); cell.classList.add('btn-hcal-left'); - cell.setAttribute('colspan', '2'); + cell.setAttribute('colspan', '3'); + /* cell = row.insertCell(); cell.textContent = itemRoom.type; cell.classList.add('hcal-cell-room-type-group-item'); cell.classList.add('btn-hcal'); cell.classList.add('btn-hcal-flat'); + */ for (var i=0; i<=$this.options.days; i++) { var dd = $this.options.startDate.clone().local().startOf('day').add(i,'d').utc(); var dd_local = dd.clone().local(); @@ -2075,7 +2078,6 @@ HotelCalendar.prototype = { 'reservationObj': $this.getReservation(this.dataset.hcalReservationObjId) }); }, false); - */ rdiv.addEventListener('mouseleave', function(ev){ $this._dispatchEvent( 'hcalOnMouseLeaveReservation', @@ -2085,6 +2087,7 @@ HotelCalendar.prototype = { 'reservationObj': $this.getReservation(this.dataset.hcalReservationObjId) }); }, false); + */ } }, @@ -2487,7 +2490,12 @@ HotelCalendar.prototype = { }; this._splitReservation = false; this._splitDate = false; + } else if ($(".marked-as-having-a-popover").length === 1) { + // TODO: better call _destroy_and_clear_popover_mark defined in hotel_calendar_controller.js + $(".marked-as-having-a-popover").popover('destroy'); + $('.hcal-reservation').removeClass("marked-as-having-a-popover"); } else { + // FIXME: Prevent multiple clicks in a row this._cellSelection.start = this._cellSelection.current = ev.target; this._cellSelection.end = false; this._updateCellSelection(); diff --git a/hotel_calendar/static/src/xml/hotel_calendar_templates.xml b/hotel_calendar/static/src/xml/hotel_calendar_templates.xml index 0c67aa1d8..793163e6d 100644 --- a/hotel_calendar/static/src/xml/hotel_calendar_templates.xml +++ b/hotel_calendar/static/src/xml/hotel_calendar_templates.xml @@ -109,59 +109,52 @@ - -
-
- + +
+
+ +
+

+
-
- -
-
- -
-
- -
-
- -
-
- -
-
-
-
- - - - - - -

This reservation is part of splitted reservation. You can check it in the corresponding Folio.

-
+
+ +
+ +

+ + +

Adults:

+

Children:

-
- -

Folio Pending

-

-
-
- -

-

Total Paid

+
+
+
+

Folio Pending

+ +

+
+ +

+
+
+
+ +

+
+ +

+
+

Total Paid

+
+
+
@@ -175,37 +168,67 @@
-
-