From 62f92758f6f7e560f8da76b880099c7ec574e788 Mon Sep 17 00:00:00 2001 From: QS5ELkMu Date: Sat, 15 Dec 2018 01:30:52 +0100 Subject: [PATCH] [IMP] Split Reservations --- hotel/models/hotel_reservation.py | 66 +++++++++++++-- hotel/wizard/split_reservation.py | 57 +------------ .../calendar/hotel_calendar_controller.js | 15 ++-- .../js/views/calendar/hotel_calendar_model.js | 9 ++ .../static/src/js/widgets/MultiCalendar.js | 20 +++++ .../src/lib/hcalendar/css/hcalendar.css | 23 +++++ .../static/src/lib/hcalendar/js/hcalendar.js | 84 ++++++++++++++----- .../models/inherited_hotel_folio.py | 4 +- 8 files changed, 186 insertions(+), 92 deletions(-) diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index d00a04909..24d359851 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -421,7 +421,7 @@ class HotelReservation(models.Model): @api.model def _autoassign(self, values): res = {} - checkin = values.get('checkin') + checkin = values.get('checkin') checkout = values.get('checkout') room_type = values.get('room_type_id') if checkin and checkout and room_type: @@ -475,21 +475,22 @@ class HotelReservation(models.Model): 'checkin': checkin or self.checkin, 'checkout': checkout or self.checkout, 'folio_id': self.folio_id.id, - # 'product_id': self.product_id.id, 'parent_reservation': self.parent_reservation.id, 'state': self.state, 'overbooking': self.overbooking, 'reselling': self.reselling, - 'price_unit': self.price_unit, + 'price_total': self.price_total, + 'price_tax': self.price_tax, + 'price_subtotal': self.price_subtotal, 'splitted': self.splitted, - # 'room_type_id': self.room_type_id.id, 'room_type_id': self.room_type_id.id, + 'room_id': self.room_id.id, } @api.constrains('adults') def _check_adults(self): for record in self: - extra_bed = record.service_ids.filtered( + extra_bed = record.service_ids.filtered( lambda r: r.product_id.is_extra_bed == True) if record.adults > record.room_id.get_capacity(len(extra_bed)): raise ValidationError( @@ -629,7 +630,7 @@ class HotelReservation(models.Model): days=self.nights, per_person=product.per_person, persons=self.adults, - old_line_days=False)) + old_line_days=False)) board_services.append((0, False, vals)) other_services = self.service_ids.filtered(lambda r: r.is_board_service == False) self.update({'service_ids': [(6, 0, other_services.ids)] + board_services}) @@ -974,6 +975,59 @@ class HotelReservation(models.Model): first_checkin = reserv.checkin return (first_checkin, last_checkout) + @api.multi + def split(self, nights): + for record in self: + date_start_dt = fields.Date.from_string(record.checkin) + date_end_dt = fields.Date.from_string(record.checkout) + date_diff = abs((date_end_dt - date_start_dt).days) + new_start_date_dt = date_start_dt + \ + timedelta(days=date_diff-nights) + if nights >= date_diff or nights < 1: + raise ValidationError(_("Invalid Nights! Max is \ + '%d'") % (date_diff-1)) + + vals = record.generate_copy_values( + new_start_date_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), + date_end_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), + ) + # Days Price + reservation_lines = [[], []] + tprice = [0.0, 0.0] + for rline in record.reservation_line_ids: + rline_dt = fields.Date.from_string(rline.date) + if rline_dt >= new_start_date_dt: + reservation_lines[1].append((0, False, { + 'date': rline.date, + 'price': rline.price + })) + tprice[1] += rline.price + reservation_lines[0].append((2, rline.id, False)) + else: + tprice[0] += rline.price + + record.write({ + 'checkout': new_start_date_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), + 'price_total': tprice[0], + 'splitted': True, + 'reservation_line_ids': reservation_lines[0], + }) + parent_res = record.parent_reservation or \ + record + vals.update({ + 'splitted': True, + 'price_total': tprice[1], + 'parent_reservation': parent_res.id, + 'room_type_id': parent_res.room_type_id.id, + 'discount': parent_res.discount, + 'reservation_line_ids': reservation_lines[1], + }) + reservation_copy = self.env['hotel.reservation'].create(vals) + if not reservation_copy: + raise ValidationError(_("Unexpected error copying record. \ + Can't split reservation!")) + return True + @api.multi def unify(self): # FIXME Remove product inheritance diff --git a/hotel/wizard/split_reservation.py b/hotel/wizard/split_reservation.py index 995649941..a50c6700d 100644 --- a/hotel/wizard/split_reservation.py +++ b/hotel/wizard/split_reservation.py @@ -18,60 +18,5 @@ class SplitReservationWizard(models.TransientModel): reservation_id = self.env['hotel.reservation'].browse( self.env.context.get('active_id')) if reservation_id: - date_start_dt = fields.Date.from_string(reservation_id.checkin) - date_end_dt = fields.Date.from_string(reservation_id.checkout) - date_diff = abs((date_end_dt - date_start_dt).days) - for record in self: - new_start_date_dt = date_start_dt + \ - timedelta(days=date_diff-record.nights) - if record.nights >= date_diff or record.nights < 1: - raise ValidationError(_("Invalid Nights! Max is \ - '%d'") % (date_diff-1)) - - vals = reservation_id.generate_copy_values( - new_start_date_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), - date_end_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), - ) - # Days Price - reservation_lines = [[], []] - tprice = [0.0, 0.0] - for rline in reservation_id.reservation_lines: - rline_dt = fields.Date.from_string(rline.date) - if rline_dt >= new_start_date_dt: - reservation_lines[1].append((0, False, { - 'date': rline.date, - 'price': rline.price - })) - tprice[1] += rline.price - reservation_lines[0].append((2, rline.id, False)) - else: - tprice[0] += rline.price - - reservation_id.write({ - 'checkout': new_start_date_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT), - 'price_unit': tprice[0], - 'splitted': True, - }) - reservation_id.reservation_lines = reservation_lines[0] - parent_res = reservation_id.parent_reservation or \ - reservation_id - vals.update({ - 'splitted': True, - 'price_unit': tprice[1], - 'parent_reservation': parent_res.id, - 'room_type_id': parent_res.room_type_id.id, - 'discount': parent_res.discount, - }) - reservation_copy = self.env['hotel.reservation'].create(vals) - if not reservation_copy: - raise ValidationError(_("Unexpected error copying record. \ - Can't split reservation!")) - reservation_copy.reservation_lines = reservation_lines[1] - # return { - # 'type': 'ir.actions.act_window', - # 'res_model': 'hotel.folio', - # 'views': [[False, "form"]], - # 'target': 'new', - # 'res_id': reservation_id.folio_id.id, - # } + reservation_id.split(self.nights) return True 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 fa62e4223..7ff3529e9 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 @@ -16,7 +16,6 @@ var AbstractController = require('web.AbstractController'), var PMSCalendarController = AbstractController.extend({ custom_events: _.extend({}, AbstractController.prototype.custom_events, { - onLoadCalendar: '_onLoadCalendar', onLoadCalendarSettings: '_onLoadCalendarSettings', onLoadViewFilters: '_onLoadViewFilters', onUpdateButtonsCounter: '_onUpdateButtonsCounter', @@ -42,12 +41,14 @@ var PMSCalendarController = AbstractController.extend({ var self = this; this._multi_calendar.setElement(this.renderer.$el.find('#hcal_widget')); - this._multi_calendar.start(); this._multi_calendar.on('tab_changed', function(ev, active_index){ if (active_index) { self._refresh_filters(active_index); } }); + this._multi_calendar.reset(); + this._multi_calendar.start(); + this._assign_multi_calendar_events(); this._load_calendars(); this._assign_view_events(); @@ -167,6 +168,7 @@ var PMSCalendarController = AbstractController.extend({ 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); }); }, @@ -302,7 +304,7 @@ var PMSCalendarController = AbstractController.extend({ this.renderer.$el.find('#pms-menu #btn_action_divide button').on('click', function(ev){ var active_calendar = self._multi_calendar.get_active_calendar(); var cur_mode = active_calendar.getSelectionMode(); - active_calendar.setSelectionMode(cur_mode===HotelCalendar.MODE.DIVIDE?HotelCalendar.MODE.NONE:HotelCalendar.MODE.DIVIDE); + active_calendar.setSelectionMode(cur_mode===HotelCalendar.ACTION.DIVIDE?HotelCalendar.MODE.NONE:HotelCalendar.ACTION.DIVIDE); }); this.renderer.$el.find('#pms-menu #btn_save_calendar_record').on('click', function(ev){ @@ -352,6 +354,9 @@ var PMSCalendarController = AbstractController.extend({ }).tooltip('show'); } }); + this._multi_calendar.on_calendar('hcalOnSplitReservation', function(ev){ + self.model.split_reservation(ev.detail.obj_id, ev.detail.nights); + }); this._multi_calendar.on_calendar('hcalOnClickReservation', function(ev){ //var res_id = ev.detail.reservationObj.getUserData('folio_id'); $(ev.detail.reservationDiv).tooltip('hide'); @@ -522,7 +527,7 @@ var PMSCalendarController = AbstractController.extend({ }); this._multi_calendar.on_calendar('hcalOnChangeSelectionMode', function(ev){ var $led = this.renderer.$el.find('#pms-menu #btn_action_divide button .led'); - if (ev.detail.newMode === HotelCalendar.MODE.DIVIDE) { + if (ev.detail.newMode === HotelCalendar.ACTION.DIVIDE) { $led.removeClass('led-disabled').addClass('led-enabled'); } else { $led.removeClass('led-enabled').addClass('led-disabled'); @@ -819,7 +824,7 @@ var PMSCalendarController = AbstractController.extend({ /* Divide Led */ var $led = this.renderer.$el.find('#pms-menu #btn_action_divide button .led'); - if (active_calendar.getSelectionMode() === HotelCalendar.MODE.DIVIDE) { + if (active_calendar.getSelectionMode() === HotelCalendar.ACTION.DIVIDE) { $led.removeClass('led-disabled').addClass('led-enabled'); } else { $led.removeClass('led-enabled').addClass('led-disabled'); 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 13fcceb19..2559a87bf 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 @@ -132,6 +132,15 @@ return AbstractModel.extend({ }); }, + split_reservation: function(id, nights) { + return this._rpc({ + model: 'hotel.reservation', + method: 'split', + args: [[id], nights], + context: Session.user_context, + }) + }, + save_changes: function(params) { params.splice(0, 0, false); // FIXME: ID=False because first parameter its an integer return this._rpc({ diff --git a/hotel_calendar/static/src/js/widgets/MultiCalendar.js b/hotel_calendar/static/src/js/widgets/MultiCalendar.js index fcef5f803..841cd3fdc 100644 --- a/hotel_calendar/static/src/js/widgets/MultiCalendar.js +++ b/hotel_calendar/static/src/js/widgets/MultiCalendar.js @@ -34,6 +34,24 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) { this.$el.on(event_name, callback.bind(this)); }, + reset: function() { + for (var i in this._calendars) { + delete this._calendars[i]; + } + for (var [$tab, $panel] of this._tabs) { + $tab.remove(); + $panel.remove(); + } + $('#multicalendar_tabs').remove(); + $('#multicalendar_panels').remove(); + this._calendars = []; + this._calendar_records = []; + this._tabs = []; + this._datasets = {}; + this._active_index = -1; + this._events = {}; + }, + get_calendar: function(index) { return this._calendars[index-1]; }, @@ -264,9 +282,11 @@ odoo.define('hotel_calendar.MultiCalendar', function(require) { this.$el.empty(); this.$tabs = $('