From a626a1ee796c43153604344c2e2d7c5922e1bcae Mon Sep 17 00:00:00 2001 From: QS5ELkMu Date: Sun, 19 Aug 2018 02:36:55 +0200 Subject: [PATCH] [WIP][MIG][11.0] Odoo Connector --- hotel_channel_connector/__manifest__.py | 1 + hotel_channel_connector/components/binder.py | 8 +- hotel_channel_connector/models/__init__.py | 10 +- .../models/hotel_reservation/common.py | 3 + .../models/hotel_virtual_room/common.py | 3 + .../hotel_virtual_room_availability/common.py | 175 ++++++++++-------- .../hotel_virtual_room_restriction/common.py | 3 + .../inherited_virtual_room_availability.py | 118 ------------ .../models/product_pricelist/common.py | 3 + 9 files changed, 127 insertions(+), 197 deletions(-) delete mode 100644 hotel_channel_connector/models/inherited_virtual_room_availability.py diff --git a/hotel_channel_connector/__manifest__.py b/hotel_channel_connector/__manifest__.py index 816b607e8..54a24d869 100644 --- a/hotel_channel_connector/__manifest__.py +++ b/hotel_channel_connector/__manifest__.py @@ -11,6 +11,7 @@ 'description': "Hotel Channel Connector Base", 'depends': [ 'hotel', + 'connector', ], 'external_dependencies': { 'python': ['xmlrpc'] diff --git a/hotel_channel_connector/components/binder.py b/hotel_channel_connector/components/binder.py index 45dd234cd..4cff79066 100644 --- a/hotel_channel_connector/components/binder.py +++ b/hotel_channel_connector/components/binder.py @@ -5,4 +5,10 @@ from odoo.addons.component.core import Component class HotelConnectorModelBinder(Component): _name = 'hotel.channel.connector.binder' _inherit = ['base.binder', 'base.hotel.channel.connector'] - _apply_on = [] + _apply_on = [ + 'channel.hotel.reservation', + 'channel.hotel.virtual.room', + 'channel.hotel.virtual.room.availability', + 'channel.hotel.virtual.room.restriction', + 'channel.product.pricelist', + ] diff --git a/hotel_channel_connector/models/__init__.py b/hotel_channel_connector/models/__init__.py index df7e001e3..d9ef21d71 100644 --- a/hotel_channel_connector/models/__init__.py +++ b/hotel_channel_connector/models/__init__.py @@ -1,13 +1,13 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). from . import res_config -from . import inherited_hotel_virtual_room -from . import inherited_product_pricelist +from . import hotel_virtual_room +from . import product_pricelist from . import inherited_product_pricelist_item -from . import inherited_reservation_restriction +from . import hotel_virtual_room_restriction from . import inherited_reservation_restriction_item -from . import inherited_virtual_room_availability -from . import inherited_hotel_reservation +from . import hotel_virtual_room_availability +from . import hotel_reservation from . import inherited_hotel_folio from . import inherited_res_partner from . import wubook_channel_info diff --git a/hotel_channel_connector/models/hotel_reservation/common.py b/hotel_channel_connector/models/hotel_reservation/common.py index ae8f05f68..a19beb11b 100644 --- a/hotel_channel_connector/models/hotel_reservation/common.py +++ b/hotel_channel_connector/models/hotel_reservation/common.py @@ -1,6 +1,9 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, models, fields +from odoo.addons.queue_job.job import job, related_action + class ChannelHotelReservation(models.Model): _name = 'channel.hotel.reservation' _inherit = 'channel.binding' diff --git a/hotel_channel_connector/models/hotel_virtual_room/common.py b/hotel_channel_connector/models/hotel_virtual_room/common.py index c652611e1..1835fb387 100644 --- a/hotel_channel_connector/models/hotel_virtual_room/common.py +++ b/hotel_channel_connector/models/hotel_virtual_room/common.py @@ -1,6 +1,9 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, models, fields +from odoo.addons.queue_job.job import job, related_action + class ChannelHotelVirtualRoom(models.Model): _name = 'channel.hotel.virtual.room' _inherit = 'channel.binding' diff --git a/hotel_channel_connector/models/hotel_virtual_room_availability/common.py b/hotel_channel_connector/models/hotel_virtual_room_availability/common.py index c9e1499ed..df322237c 100644 --- a/hotel_channel_connector/models/hotel_virtual_room_availability/common.py +++ b/hotel_channel_connector/models/hotel_virtual_room_availability/common.py @@ -1,6 +1,9 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, models, fields +from odoo.addons.queue_job.job import job, related_action + class ChannelHotelVirtualRoomAvailability(models.Model): _name = 'channel.hotel.virtual.room.availability' _inherit = 'channel.binding' @@ -23,94 +26,120 @@ class ChannelHotelVirtualRoomAvailability(models.Model): channel_pushed = fields.Boolean("Channel Pushed", readonly=True, default=False, old_name='wpushed') - @job(default_channel='root.channel') - @related_action(action='related_action_unwrap_binding') - @api.multi - def create_plan(self): - self.ensure_one() - if self._context.get('channel_action', True): - with self.backend_id.work_on(self._name) as work: - adapter = work.component(usage='backend.adapter') - try: - channel_plan_id = adapter.create_plan(self.name, - self.is_daily_plan and 1 or 0) - if channel_plan_id: - self.channel_plan_id = channel_plan_id - except ValidationError as e: - self.create_issue('room', "Can't create plan on channel", "sss") + @api.constrains('channel_max_avail') + def _check_wmax_avail(self): + for record in self: + if record.channel_max_avail > record.virtual_room_id.total_rooms_count: + raise ValidationError(_("max avail for channel can't be high \ + than toal rooms \ + count: %d") % record.virtual_room_id.total_rooms_count) @job(default_channel='root.channel') @related_action(action='related_action_unwrap_binding') @api.multi - def update_plan_name(self): + def update_availability(self): self.ensure_one() if self._context.get('channel_action', True): with self.backend_id.work_on(self._name) as work: adapter = work.component(usage='backend.adapter') - try: - adapter.update_plan_name( - self.channel_plan_id, - self.name) - except ValidationError as e: - self.create_issue('room', "Can't update plan name on channel", "sss") + date_dt = date_utils.get_datetime(self.date) + adapter.update_availability([{ + 'id': self.virtual_room_id.channel_room_id, + 'days': [{ + 'date': date_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), + 'avail': self.avail, + }], + }]) - @job(default_channel='root.channel') - @related_action(action='related_action_unwrap_binding') - @api.multi - def delete_plan(self): - self.ensure_one() - if self._context.get('channel_action', True) and self.channel_room_id: - with self.backend_id.work_on(self._name) as work: - adapter = work.component(usage='backend.adapter') - try: - adapter.delete_plan(self.channel_plan_id) - except ValidationError as e: - self.create_issue('room', "Can't delete plan on channel", "sss") - - @job(default_channel='root.channel') - @api.multi - def import_price_plans(self): - if self._context.get('channel_action', True): - with self.backend_id.work_on(self._name) as work: - importer = work.component(usage='channel.importer') - return importer.import_pricing_plans() - -class ProductPricelist(models.Model): - _inherit = 'product.pricelist' +class HotelVirtualRoomAvailability(models.Model): + _inherit = 'hotel.virtual.room.availability' channel_bind_ids = fields.One2many( - comodel_name='channel.product.pricelist', + comodel_name='channel.hotel.virtual.room.availability', inverse_name='odoo_id', - string='Hotel Channel Connector Bindings') + string='Hotel Virtual Room Availability Connector Bindings') + + @api.constrains('avail') + def _check_avail(self): + vroom_obj = self.env['hotel.virtual.room'] + issue_obj = self.env['hotel.channel.connector.issue'] + for record in self: + cavail = len(vroom_obj.check_availability_virtual_room( + record.date, + record.date, + virtual_room_id=record.virtual_room_id.id)) + max_avail = min(cavail, record.virtual_room_id.total_rooms_count) + if record.avail > max_avail: + issue_obj.sudo().create({ + 'section': 'avail', + 'message': _(r"The new availability can't be greater than \ + the actual availability \ + \n[%s]\nInput: %d\Limit: %d") % (record.virtual_room_id.name, + record.avail, + record), + 'wid': record.virtual_room_id.wrid, + 'date_start': record.date, + 'date_end': record.date, + }) + # Auto-Fix wubook availability + self._event('on_fix_channel_availability').notify(record) + return super(HotelVirtualRoomAvailability, self)._check_avail() + + @api.onchange('virtual_room_id') + def onchange_virtual_room_id(self): + if self.virtual_room_id: + self.channel_max_avail = self.virtual_room_id.max_real_rooms @api.multi - @api.depends('name') - def name_get(self): - pricelist_obj = self.env['product.pricelist'] - org_names = super(ProductPricelist, self).name_get() - names = [] - for name in org_names: - priclist_id = pricelist_obj.browse(name[0]) - if priclist_id.wpid: - names.append((name[0], '%s (WuBook)' % name[1])) - else: - names.append((name[0], name[1])) - return names + def write(self, vals): + if self._context.get('channel_action', True): + vals.update({'channel_pushed': False}) + return super(HotelVirtualRoomAvailability, self).write(vals) -class ChannelBindingProductPricelistListener(Component): - _name = 'channel.binding.product.pricelist.listener' + @api.model + def refresh_availability(self, checkin, checkout, product_id): + date_start = date_utils.get_datetime(checkin) + # Not count end day of the reservation + date_diff = date_utils.date_diff(checkin, checkout, hours=False) + + vroom_obj = self.env['hotel.virtual.room'] + virtual_room_avail_obj = self.env['hotel.virtual.room.availability'] + + vrooms = vroom_obj.search([ + ('room_ids.product_id', '=', product_id) + ]) + for vroom in vrooms: + if vroom.channel_room_id: + for i in range(0, date_diff): + ndate_dt = date_start + timedelta(days=i) + ndate_str = ndate_dt.strftime(DEFAULT_SERVER_DATE_FORMAT) + avail = len(vroom_obj.check_availability_virtual_room( + ndate_str, + ndate_str, + virtual_room_id=vroom.id)) + max_avail = vroom.max_real_rooms + vroom_avail_id = virtual_room_avail_obj.search([ + ('virtual_room_id', '=', vroom.id), + ('date', '=', ndate_str)], limit=1) + if vroom_avail_id and vroom_avail_id.channel_max_avail >= 0: + max_avail = vroom_avail_id.channel_max_avail + avail = max( + min(avail, vroom.total_rooms_count, max_avail), 0) + + if vroom_avail_id: + vroom_avail_id.write({'avail': avail}) + else: + virtual_room_avail_obj.create({ + 'virtual_room_id': vroom.id, + 'date': ndate_str, + 'avail': avail, + }) + +class ChannelBindingHotelVirtualRoomAvailabilityListener(Component): + _name = 'channel.binding.hotel.virtual.room.availability.listener' _inherit = 'base.connector.listener' - _apply_on = ['channel.product.pricelist'] + _apply_on = ['channel.hotel.virtual.room.availability'] @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) - def on_record_write(self, record, fields=None): - record.with_delay(priority=20).create_plan() - - @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) - def on_record_unlink(self, record, fields=None): - record.with_delay(priority=20).delete_plan() - - @skip_if(lambda self, record, **kwargs: self.no_connector_export(record)) - def on_record_write(self, record, fields=None): - if 'name' in fields: - record.with_delay(priority=20).update_plan_name() + def on_fix_channel_availability(self, record, fields=None): + record.with_delay(priority=20).update_availability() diff --git a/hotel_channel_connector/models/hotel_virtual_room_restriction/common.py b/hotel_channel_connector/models/hotel_virtual_room_restriction/common.py index ae4aee64b..67a73d978 100644 --- a/hotel_channel_connector/models/hotel_virtual_room_restriction/common.py +++ b/hotel_channel_connector/models/hotel_virtual_room_restriction/common.py @@ -1,6 +1,9 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, models, fields +from odoo.addons.queue_job.job import job, related_action + class ChannelHotelVirtualRoomRestriction(models.Model): _name = 'channel.hotel.virtual.room.restriction' _inherit = 'channel.binding' diff --git a/hotel_channel_connector/models/inherited_virtual_room_availability.py b/hotel_channel_connector/models/inherited_virtual_room_availability.py deleted file mode 100644 index cd0cfdd00..000000000 --- a/hotel_channel_connector/models/inherited_virtual_room_availability.py +++ /dev/null @@ -1,118 +0,0 @@ -# Copyright 2018 Alexandre Díaz -# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from datetime import timedelta -from openerp import models, fields, api, _ -from openerp.exceptions import ValidationError -from openerp.tools import DEFAULT_SERVER_DATE_FORMAT -from odoo.addons.hotel import date_utils -from ..wubook import DEFAULT_WUBOOK_DATE_FORMAT - - -class VirtualRoomAvailability(models.Model): - _inherit = 'hotel.virtual.room.availability' - - @api.model - def _default_channel_max_avail(self): - if self.virtual_room_id: - return self.virtual_room_id.max_real_rooms - return -1 - - channel_max_avail = fields.Integer("Max. Channel Avail", - default=_default_channel_max_avail, - old_name='wmax_avail') - channel_pushed = fields.Boolean("Channel Pushed", readonly=True, default=False, - old_name='wpushed') - - @api.constrains('avail') - def _check_avail(self): - vroom_obj = self.env['hotel.virtual.room'] - issue_obj = self.env['hotel.channel.connector.issue'] - wubook_obj = self.env['wubook'] - for record in self: - cavail = len(vroom_obj.check_availability_virtual_room( - record.date, - record.date, - virtual_room_id=record.virtual_room_id.id)) - max_avail = min(cavail, record.virtual_room_id.total_rooms_count) - if record.avail > max_avail: - issue_obj.sudo().create({ - 'section': 'avail', - 'message': _(r"The new availability can't be greater than \ - the actual availability \ - \n[%s]\nInput: %d\Limit: %d") % (record.virtual_room_id.name, - record.avail, - record), - 'wid': record.virtual_room_id.wrid, - 'date_start': record.date, - 'date_end': record.date, - }) - # Auto-Fix wubook availability - date_dt = date_utils.get_datetime(record.date) - wubook_obj.update_availability([{ - 'id': record.virtual_room_id.wrid, - 'days': [{ - 'date': date_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - 'avail': max_avail, - }], - }]) - return super(VirtualRoomAvailability, self)._check_avail() - - @api.constrains('wmax_avail') - def _check_wmax_avail(self): - for record in self: - if record.wmax_avail > record.virtual_room_id.total_rooms_count: - raise ValidationError(_("max avail for wubook can't be high \ - than toal rooms \ - count: %d") % record.virtual_room_id.total_rooms_count) - - @api.onchange('virtual_room_id') - def onchange_virtual_room_id(self): - if self.virtual_room_id: - self.wmax_avail = self.virtual_room_id.max_real_rooms - - @api.multi - def write(self, vals): - if self._context.get('wubook_action', True) and \ - self.env['wubook'].is_valid_account(): - vals.update({'wpushed': False}) - return super(VirtualRoomAvailability, self).write(vals) - - @api.model - def refresh_availability(self, checkin, checkout, product_id): - date_start = date_utils.get_datetime(checkin) - # Not count end day of the reservation - date_diff = date_utils.date_diff(checkin, checkout, hours=False) - - vroom_obj = self.env['hotel.room.type'] - virtual_room_avail_obj = self.env['hotel.virtual.room.availability'] - - vrooms = vroom_obj.search([ - ('room_ids.product_id', '=', product_id) - ]) - for vroom in vrooms: - if vroom.wrid and vroom.wrid != '': - for i in range(0, date_diff): - ndate_dt = date_start + timedelta(days=i) - ndate_str = ndate_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT) - avail = len(vroom_obj.check_availability_virtual_room( - ndate_str, - ndate_str, - virtual_room_id=vroom.id)) - max_avail = vroom.max_real_rooms - vroom_avail_id = virtual_room_avail_obj.search([ - ('virtual_room_id', '=', vroom.id), - ('date', '=', ndate_str)], limit=1) - if vroom_avail_id and vroom_avail_id.wmax_avail >= 0: - max_avail = vroom_avail_id.wmax_avail - avail = max( - min(avail, vroom.total_rooms_count, max_avail), 0) - - if vroom_avail_id: - vroom_avail_id.write({'avail': avail}) - else: - virtual_room_avail_obj.create({ - 'virtual_room_id': vroom.id, - 'date': ndate_str, - 'avail': avail, - }) diff --git a/hotel_channel_connector/models/product_pricelist/common.py b/hotel_channel_connector/models/product_pricelist/common.py index aed0a90bc..b07f9800b 100644 --- a/hotel_channel_connector/models/product_pricelist/common.py +++ b/hotel_channel_connector/models/product_pricelist/common.py @@ -1,6 +1,9 @@ # Copyright 2018 Alexandre Díaz # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import api, models, fields +from odoo.addons.queue_job.job import job, related_action + class ChannelProductPricelist(models.Model): _name = 'channel.product.pricelist' _inherit = 'channel.binding'