From 3837452adf607a906a70628d459a86006060d731 Mon Sep 17 00:00:00 2001 From: Pablo Date: Mon, 11 Mar 2019 11:00:32 +0100 Subject: [PATCH] [UPD] Update channel availability for segmentation management --- .../models/hotel_reservation/common.py | 8 +-- .../hotel_room_type_availability/common.py | 18 +++++-- .../models/inherited_hotel_room.py | 53 ++++++++++++++++--- .../models/hotel_reservation/common.py | 33 +++++++++--- 4 files changed, 89 insertions(+), 23 deletions(-) diff --git a/hotel_channel_connector/models/hotel_reservation/common.py b/hotel_channel_connector/models/hotel_reservation/common.py index b161b81c3..6dd98e33b 100644 --- a/hotel_channel_connector/models/hotel_reservation/common.py +++ b/hotel_channel_connector/models/hotel_reservation/common.py @@ -105,7 +105,7 @@ class ChannelHotelReservation(models.Model): channel_room_type_avail_obj = self.env['channel.hotel.room.type.availability'] for record in vals: # FIX: 3rd parameters is backend_id, use room_id=record['room_id'] instead - channel_room_type_avail_obj.refresh_availability( + channel_room_type_avail_obj.sudo().refresh_availability( record['checkin'], record['checkout'], record['backend_id'], @@ -174,7 +174,7 @@ class HotelReservation(models.Model): ('odoo_id', '=', vals['room_type_id']) ]).backend_id # WARNING: more than one backend_id is currently not expected - self.env['channel.hotel.room.type.availability'].refresh_availability( + self.env['channel.hotel.room.type.availability'].sudo().refresh_availability( checkin=vals['real_checkin'], checkout=vals['real_checkout'], backend_id=backend_id.id, @@ -219,14 +219,14 @@ class HotelReservation(models.Model): channel_room_type_avail_obj = self.env['channel.hotel.room.type.availability'] for k_i, v_i in enumerate(old_vals): - channel_room_type_avail_obj.refresh_availability( + channel_room_type_avail_obj.sudo().refresh_availability( checkin=v_i['checkin'], checkout=v_i['checkout'], backend_id=v_i['backend_id'], room_id=v_i['room_id']) # NOTE: A reservation can be moved into a room type not connected to any channel if new_backend_id: - channel_room_type_avail_obj.refresh_availability( + channel_room_type_avail_obj.sudo().refresh_availability( checkin=new_vals[k_i]['checkin'], checkout=new_vals[k_i]['checkout'], backend_id=new_vals[k_i]['backend_id'], diff --git a/hotel_channel_connector/models/hotel_room_type_availability/common.py b/hotel_channel_connector/models/hotel_room_type_availability/common.py index 632dde221..af82f545b 100644 --- a/hotel_channel_connector/models/hotel_room_type_availability/common.py +++ b/hotel_channel_connector/models/hotel_room_type_availability/common.py @@ -177,11 +177,23 @@ class ChannelHotelRoomTypeAvailability(models.Model): if room_type_avail_id.channel_avail != avail: vals_avail.update({'channel_avail': avail}) if vals_avail: - room_type_avail_id.sudo().write(vals_avail) + room_type_avail_id.write(vals_avail) + + # Auto-Fix channel quota and max availability + vals_avail = {} + if room_type_avail_id.quota > avail: + vals_avail.update({'quota': avail}) + _logger.info(vals_avail) + if room_type_avail_id.max_avail > avail: + vals_avail.update({'max_avail': avail}) + if vals_avail: + room_type_avail_id.with_context( + {'connector_no_export': True} + ).write(vals_avail) else: self.env['hotel.room.type.availability'].with_context( {'connector_no_export': True} - ).sudo().create({ + ).create({ 'room_type_id': room_type_bind.odoo_id.id, 'date': ndate_str, 'quota': quota, @@ -191,7 +203,7 @@ class ChannelHotelRoomTypeAvailability(models.Model): 'backend_id': backend_id, })] }) - self.sudo().push_availability(self.env['channel.backend'].browse(backend_id)) + self.push_availability(self.env['channel.backend'].browse(backend_id)) @job(default_channel='root.channel') @api.model diff --git a/hotel_channel_connector/models/inherited_hotel_room.py b/hotel_channel_connector/models/inherited_hotel_room.py index c03345004..e06527c7e 100644 --- a/hotel_channel_connector/models/inherited_hotel_room.py +++ b/hotel_channel_connector/models/inherited_hotel_room.py @@ -1,7 +1,9 @@ # Copyright 2019 Pablo Q. Barriuso # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, api +from datetime import timedelta +from odoo import models, api, fields +from odoo.tools import DEFAULT_SERVER_DATE_FORMAT class HotelRoom(models.Model): @@ -23,13 +25,48 @@ class HotelRoom(models.Model): res = super().write(vals) for item in room_type_ids: - if item['new_room_type_id'] != item['old_room_type_id']: - self.env['channel.hotel.room.type'].search( - [('odoo_id', '=', item['old_room_type_id'])] - )._onchange_availability() - self.env['channel.hotel.room.type'].search( - [('odoo_id', '=', item['new_room_type_id'])] - )._onchange_availability() + if item['new_room_type_id'] != item['old_room_type_id']: + old_channel_room_type = self.env['channel.hotel.room.type'].search([ + ('odoo_id', '=', item['old_room_type_id']) + ]) + old_channel_room_type._onchange_availability() + channel_availability = self.env['channel.hotel.room.type.availability'].search([ + ('room_type_id', '=', item['old_room_type_id']), + '|', + ('quota', '>', old_channel_room_type.total_rooms_count), + ('max_avail', '>', old_channel_room_type.total_rooms_count), + ], order='date asc') or False + if channel_availability: + date_range = channel_availability.mapped('date') + dfrom = date_range[0] + dto = (fields.Date.from_string(date_range[-1]) + timedelta(days=1)).strftime( + DEFAULT_SERVER_DATE_FORMAT) + self.env['channel.hotel.room.type.availability'].refresh_availability( + checkin=dfrom, + checkout=dto, + backend_id=1, + room_type_id=item['old_room_type_id'],) + + new_channel_room_type = self.env['channel.hotel.room.type'].search([ + ('odoo_id', '=', item['new_room_type_id']) + ]) + new_channel_room_type._onchange_availability() + channel_availability = self.env['channel.hotel.room.type.availability'].search([ + ('room_type_id', '=', item['new_room_type_id']), + '|', + ('quota', '>', new_channel_room_type.total_rooms_count), + ('max_avail', '>', new_channel_room_type.total_rooms_count), + ], order='date asc') or False + if channel_availability: + date_range = channel_availability.mapped('date') + dfrom = date_range[0] + dto = (fields.Date.from_string(date_range[-1]) + timedelta(days=1)).strftime( + DEFAULT_SERVER_DATE_FORMAT) + self.env['channel.hotel.room.type.availability'].refresh_availability( + checkin=dfrom, + checkout=dto, + backend_id=1, + room_type_id=item['new_room_type_id'], ) else: res = super().write(vals) return res diff --git a/hotel_channel_connector_wubook/models/hotel_reservation/common.py b/hotel_channel_connector_wubook/models/hotel_reservation/common.py index 4ed069b2e..2df0ae844 100644 --- a/hotel_channel_connector_wubook/models/hotel_reservation/common.py +++ b/hotel_channel_connector_wubook/models/hotel_reservation/common.py @@ -4,6 +4,7 @@ from odoo import api, models, fields, _ from odoo.exceptions import ValidationError from odoo.addons.component.core import Component +from odoo.addons.component_event import skip_if from odoo.addons.hotel_channel_connector_wubook.components.backend_adapter import ( WUBOOK_STATUS_CONFIRMED, WUBOOK_STATUS_WAITING, @@ -59,14 +60,7 @@ class HotelReservation(models.Model): if user.has_group('hotel.group_hotel_call'): self.write({'to_assign': True}) - res = super(HotelReservation, self).action_cancel() - for record in self: - # Only can cancel reservations created directly in wubook - for binding in record.channel_bind_ids: - if binding.external_id and not binding.ota_id and \ - int(binding.channel_status) in WUBOOK_STATUS_GOOD: - self.sudo().env['channel.hotel.reservation']._event('on_record_cancel').notify(binding) - return res + return super(HotelReservation, self).action_cancel() @api.multi def confirm(self): @@ -79,6 +73,26 @@ class HotelReservation(models.Model): return super(HotelReservation, self).confirm() +class BindingHotelReservationListener(Component): + _name = 'binding.hotel.reservation.listener' + _inherit = 'base.connector.listener' + _apply_on = ['hotel.reservation'] + + @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) + def on_record_write(self, record, fields=None): + + fields_to_check = ('state', ) + fields_checked = [elm for elm in fields_to_check if elm in fields] + if any(fields_checked): + for record in self: + # Only can cancel reservations created directly in wubook + for binding in record.channel_bind_ids: + if binding.external_id and not binding.ota_id and \ + int(binding.channel_status) in WUBOOK_STATUS_GOOD: + binding.sudo().cancel_reservation() + # self.env['channel.hotel.reservation']._event('on_record_cancel').notify(binding) + + class HotelReservationAdapter(Component): _name = 'channel.hotel.reservation.adapter' _inherit = 'wubook.adapter' @@ -91,6 +105,9 @@ class HotelReservationAdapter(Component): def fetch_new_bookings(self): return super(HotelReservationAdapter, self).fetch_new_bookings() + def fetch_bookings(self, dfrom, dto): + return super(HotelReservationAdapter, self).fetch_bookings(dfrom, dto) + def fetch_booking(self, channel_reservation_id): return super(HotelReservationAdapter, self).fetch_booking( channel_reservation_id)