From 0234d75fd9403cc1461281da76e1d38f7a6241db Mon Sep 17 00:00:00 2001 From: QS5ELkMu Date: Tue, 21 Aug 2018 01:32:31 +0200 Subject: [PATCH] [WIP][MIG][11.0] Odoo Connector --- hotel_calendar/__manifest__.py | 4 +- hotel_calendar/models/__init__.py | 6 +- hotel_calendar/models/bus_hotel_calendar.py | 6 +- ...l_room.py => inherited_hotel_room_type.py} | 10 +- .../models/inherited_product_pricelist.py | 8 +- .../inherited_product_pricelist_item.py | 66 +- ...ist_cached.py => room_pricelist_cached.py} | 8 +- .../calendar/hotel_calendar_controller.js | 2 +- .../js/views/calendar/hotel_calendar_model.js | 2 +- hotel_calendar/views/actions.xml | 40 +- hotel_calendar/views/general.xml | 48 +- .../views/inherited_hotel_room_type_views.xml | 14 + .../views/inherited_hotel_room_views.xml | 8 +- .../inherited_hotel_virtual_room_views.xml | 14 - .../views/inherited_res_users_views.xml | 66 +- .../views/room_pricelist_cached_views.xml | 34 + .../virtual_room_pricelist_cached_views.xml | 35 - .../src/js/views/hotel_calendar_model.js | 119 -- .../views/general.xml | 15 +- .../components/importer.py | 12 +- .../wizard/wubook_import_availability.py | 10 +- hotel_channel_connector/wubook.py | 1760 ----------------- 22 files changed, 204 insertions(+), 2083 deletions(-) rename hotel_calendar/models/{inherited_hotel_virtual_room.py => inherited_hotel_room_type.py} (65%) rename hotel_calendar/models/{virtual_room_pricelist_cached.py => room_pricelist_cached.py} (61%) create mode 100644 hotel_calendar/views/inherited_hotel_room_type_views.xml delete mode 100644 hotel_calendar/views/inherited_hotel_virtual_room_views.xml create mode 100644 hotel_calendar/views/room_pricelist_cached_views.xml delete mode 100644 hotel_calendar/views/virtual_room_pricelist_cached_views.xml delete mode 100644 hotel_calendar_channel_connector/static/src/js/views/hotel_calendar_model.js delete mode 100644 hotel_channel_connector/wubook.py diff --git a/hotel_calendar/__manifest__.py b/hotel_calendar/__manifest__.py index 15e0b71cf..1af70e996 100644 --- a/hotel_calendar/__manifest__.py +++ b/hotel_calendar/__manifest__.py @@ -24,9 +24,9 @@ 'views/actions.xml', 'views/res_config_views.xml', 'views/inherited_res_users_views.xml', - 'views/inherited_hotel_virtual_room_views.xml', + 'views/inherited_hotel_room_type_views.xml', 'views/inherited_hotel_room_views.xml', - 'views/virtual_room_pricelist_cached_views.xml', + 'views/room_pricelist_cached_views.xml', 'data/views.xml', 'data/menus.xml', 'data/records.xml', diff --git a/hotel_calendar/models/__init__.py b/hotel_calendar/models/__init__.py index 162b5fde3..49d1e3b7a 100644 --- a/hotel_calendar/models/__init__.py +++ b/hotel_calendar/models/__init__.py @@ -4,13 +4,15 @@ from . import inherited_hotel_reservation from . import inherited_product_pricelist_item from . import inherited_res_users from . import bus_hotel_calendar -from . import virtual_room_pricelist_cached +from . import room_pricelist_cached from . import hotel_calendar_management from . import res_config -from . import inherited_hotel_virtual_room from . import inherited_hotel_room +from . import inherited_hotel_room_type from . import inherited_hotel_virtual_room_restriction_item from . import inherited_hotel_virtual_room_availability from . import inherited_product_pricelist from . import inherited_hotel_folio from . import inherited_ir_default +from . import inherited_ir_actions_act_window_view +from . import inherited_ir_ui_view diff --git a/hotel_calendar/models/bus_hotel_calendar.py b/hotel_calendar/models/bus_hotel_calendar.py index 96f296231..5e73bddef 100644 --- a/hotel_calendar/models/bus_hotel_calendar.py +++ b/hotel_calendar/models/bus_hotel_calendar.py @@ -77,7 +77,7 @@ class BusHotelCalendar(models.TransientModel): 'days': { date_dt.strftime("%d/%m/%Y"): vals['price'], }, - 'room': vals['virtual_room_id'], + 'room': vals['room_id'], 'id': vals['id'], }], }, @@ -89,7 +89,7 @@ class BusHotelCalendar(models.TransientModel): return { 'type': 'restriction', 'restriction': { - vals['virtual_room_id']: { + vals['room_id']: { date_dt.strftime("%d/%m/%Y"): [ vals['min_stay'], vals['min_stay_arrival'], @@ -110,7 +110,7 @@ class BusHotelCalendar(models.TransientModel): return { 'type': 'availability', 'availability': { - vals['virtual_room_id']: { + vals['room_id']: { date_dt.strftime("%d/%m/%Y"): [ vals['avail'], vals['no_ota'], diff --git a/hotel_calendar/models/inherited_hotel_virtual_room.py b/hotel_calendar/models/inherited_hotel_room_type.py similarity index 65% rename from hotel_calendar/models/inherited_hotel_virtual_room.py rename to hotel_calendar/models/inherited_hotel_room_type.py index 815d6225d..87d160e07 100644 --- a/hotel_calendar/models/inherited_hotel_virtual_room.py +++ b/hotel_calendar/models/inherited_hotel_room_type.py @@ -3,19 +3,19 @@ from odoo import models, fields, api -class HotelVirtualRoom(models.Model): +class HotelRoomType(models.Model): _inherit = 'hotel.room.type' hcal_sequence = fields.Integer('Calendar Sequence', default=0) @api.multi def unlink(self): - vroom_pr_cached_obj = self.env['virtual.room.pricelist.cached'] + room_type_pr_cached_obj = self.env['hotel.room.pricelist.cached'] for record in self: - pr_chached = vroom_pr_cached_obj.search([ - ('virtual_room_id', '=', record.id) + pr_chached = room_type_pr_cached_obj.search([ + ('room_id', '=', record.id) ]) # Because 'pricelist.cached' is an isolated model, # doesn't trigger 'ondelete'. Need call 'unlink' instead. pr_chached.unlink() - return super(HotelVirtualRoom, self).unlink() + return super(HotelRoomType, self).unlink() diff --git a/hotel_calendar/models/inherited_product_pricelist.py b/hotel_calendar/models/inherited_product_pricelist.py index 651d4d8cf..6a51e4808 100644 --- a/hotel_calendar/models/inherited_product_pricelist.py +++ b/hotel_calendar/models/inherited_product_pricelist.py @@ -7,13 +7,13 @@ class ProductPricelist(models.Model): _inherit = 'product.pricelist' @api.multi - def update_price(self, virtual_room_id, date, price): - vroom = self.env['hotel.room.type'].browse(virtual_room_id) + def update_price(self, room_type_id, date, price): + room_type = self.env['hotel.room.type'].browse(room_type_id) pritem_obj = self.env['product.pricelist.item'] for record in self: plitem = pritem_obj.search([ ('pricelist_id', '=', record.id), - ('product_tmpl_id', '=', vroom.product_id.product_tmpl_id.id), + ('product_tmpl_id', '=', room_type.product_id.product_tmpl_id.id), ('date_start', '=', date), ('date_end', '=', date), ('applied_on', '=', '1_product'), @@ -24,7 +24,7 @@ class ProductPricelist(models.Model): else: pritem_obj.create({ 'pricelist_id': record.id, - 'product_tmpl_id': vroom.product_id.product_tmpl_id.id, + 'product_tmpl_id': room_type.product_id.product_tmpl_id.id, 'date_start': date, 'date_end': date, 'applied_on': '1_product', diff --git a/hotel_calendar/models/inherited_product_pricelist_item.py b/hotel_calendar/models/inherited_product_pricelist_item.py index 309c6d55b..af76d6538 100644 --- a/hotel_calendar/models/inherited_product_pricelist_item.py +++ b/hotel_calendar/models/inherited_product_pricelist_item.py @@ -10,17 +10,17 @@ class ProductPricelistItem(models.Model): def create(self, vals): res = super(ProductPricelistItem, self).create(vals) pricelist_parity_id = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'parity_pricelist_id') + 'res.config.settings', 'parity_pricelist_id') if pricelist_parity_id: pricelist_parity_id = int(pricelist_parity_id) pricelist_id = res.pricelist_id.id product_tmpl_id = res.product_tmpl_id.id date_start = res.date_start - vroom = self.env['hotel.room.type'].search([ + room_type = self.env['hotel.room.type'].search([ ('product_id.product_tmpl_id', '=', product_tmpl_id) ], limit=1) if pricelist_id == pricelist_parity_id and vroom: - prod = vroom.product_id.with_context( + prod = room_type.product_id.with_context( quantity=1, date=date_start, pricelist=pricelist_id) @@ -29,21 +29,21 @@ class ProductPricelistItem(models.Model): self.env['bus.hotel.calendar'].send_pricelist_notification({ 'pricelist_id': pricelist_id, 'date': date_start, - 'virtual_room_id': vroom.id, + 'room_id': room_type.id, 'price': prod_price, 'id': self.id, }) - vroom_pr_cached_obj = self.env['virtual.room.pricelist.cached'] - vroom_pr_cached_id = vroom_pr_cached_obj.search([ - ('virtual_room_id', '=', vroom.id), + room_pr_cached_obj = self.env['room.pricelist.cached'] + room_pr_cached_id = room_pr_cached_obj.search([ + ('room_id', '=', room_type.id), ('date', '=', date_start), ], limit=1) - if vroom_pr_cached_id: - vroom_pr_cached_id.write({'price': prod_price}) + if room_pr_cached_id: + room_pr_cached_id.write({'price': prod_price}) else: - vroom_pr_cached_obj.create({ - 'virtual_room_id': vroom.id, + room_pr_cached_obj.create({ + 'room_id': room_type.id, 'date': date_start, 'price': prod_price, }) @@ -52,14 +52,14 @@ class ProductPricelistItem(models.Model): @api.multi def write(self, vals): pricelist_parity_id = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'parity_pricelist_id') + 'res.config.settings', 'parity_pricelist_id') if pricelist_parity_id: pricelist_parity_id = int(pricelist_parity_id) ret_vals = super(ProductPricelistItem, self).write(vals) - vroom_pr_cached_obj = self.env['virtual.room.pricelist.cached'] + room_pr_cached_obj = self.env['room.pricelist.cached'] bus_calendar_obj = self.env['bus.hotel.calendar'] - vroom_obj = self.env['hotel.room.type'] + room_type_obj = self.env['hotel.room.type'] if vals.get('fixed_price'): for record in self: pricelist_id = vals.get('pricelist_id') or \ @@ -69,12 +69,12 @@ class ProductPricelistItem(models.Model): date_start = vals.get('date_start') or record.date_start product_tmpl_id = vals.get('product_tmpl_id') or \ record.product_tmpl_id.id - vroom = vroom_obj.search([ + room_type = room_type_obj.search([ ('product_id.product_tmpl_id', '=', product_tmpl_id) ], limit=1) - if vroom and date_start: - prod = vroom.product_id.with_context( + if room_type and date_start: + prod = room_type.product_id.with_context( quantity=1, date=date_start, pricelist=pricelist_id) @@ -83,20 +83,20 @@ class ProductPricelistItem(models.Model): bus_calendar_obj.send_pricelist_notification({ 'pricelist_id': pricelist_id, 'date': date_start, - 'virtual_room_id': vroom.id, + 'room_id': room_type.id, 'price': prod_price, 'id': record.id, }) - vroom_pr_cached_id = vroom_pr_cached_obj.search([ - ('virtual_room_id', '=', vroom.id), + vroom_pr_cached_id = room_pr_cached_obj.search([ + ('room_id', '=', room_type.id), ('date', '=', date_start), ], limit=1) if vroom_pr_cached_id: vroom_pr_cached_id.write({'price': prod_price}) else: - vroom_pr_cached_obj.create({ - 'virtual_room_id': vroom.id, + room_pr_cached_obj.create({ + 'room_id': room_type.id, 'date': date_start, 'price': prod_price, }) @@ -105,7 +105,7 @@ class ProductPricelistItem(models.Model): @api.multi def unlink(self): pricelist_parity_id = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'parity_pricelist_id') + 'res.config.settings', 'parity_pricelist_id') if pricelist_parity_id: pricelist_parity_id = int(pricelist_parity_id) # Construct dictionary with relevant info of removed records @@ -113,25 +113,25 @@ class ProductPricelistItem(models.Model): for record in self: if record.pricelist_id.id != pricelist_parity_id: continue - vroom = self.env['hotel.room.type'].search([ + room_type = self.env['hotel.room.type'].search([ ('product_id.product_tmpl_id', '=', record.product_tmpl_id.id) ], limit=1) unlink_vals.append({ 'pricelist_id': record.pricelist_id.id, 'date': record.date_start, - 'vroom': vroom, + 'room': room_type, 'id': record.id, }) # Do Normal Stuff res = super(ProductPricelistItem, self).unlink() # Do extra operations - vroom_pr_cached_obj = self.env['virtual.room.pricelist.cached'] + room_pr_cached_obj = self.env['room.pricelist.cached'] bus_calendar_obj = self.env['bus.hotel.calendar'] for vals in unlink_vals: pricelist_id = vals['pricelist_id'] date_start = vals['date'] - vroom = vals['vroom'] - prod = vroom.product_id.with_context( + room_type = vals['room'] + prod = room_type.product_id.with_context( quantity=1, date=date_start, pricelist=pricelist_id) @@ -140,16 +140,16 @@ class ProductPricelistItem(models.Model): bus_calendar_obj.send_pricelist_notification({ 'pricelist_id': pricelist_id, 'date': date_start, - 'virtual_room_id': vroom.id, + 'room_id': room_type.id, 'price': prod.price, 'id': vals['id'], }) # Remove records from cache model - vroom_pr_cached_id = vroom_pr_cached_obj.search([ - ('virtual_room_id', '=', vroom.id), + room_pr_cached_id = room_pr_cached_obj.search([ + ('room_id', '=', room_type.id), ('date', '=', date_start), ], limit=1) - if vroom_pr_cached_id: - vroom_pr_cached_id.unlink() + if room_pr_cached_id: + room_pr_cached_id.unlink() return res diff --git a/hotel_calendar/models/virtual_room_pricelist_cached.py b/hotel_calendar/models/room_pricelist_cached.py similarity index 61% rename from hotel_calendar/models/virtual_room_pricelist_cached.py rename to hotel_calendar/models/room_pricelist_cached.py index 5ec8fd32d..3514150b3 100644 --- a/hotel_calendar/models/virtual_room_pricelist_cached.py +++ b/hotel_calendar/models/room_pricelist_cached.py @@ -4,14 +4,14 @@ from odoo import models, fields, api from odoo.exceptions import ValidationError -class VirtualRoomPricelistCached(models.Model): +class RoomPricelistCached(models.Model): ''' Cached Pricelist. Used only for Calendar Values ''' - _name = 'virtual.room.pricelist.cached' + _name = 'room.pricelist.cached' - virtual_room_id = fields.Many2one('hotel.room.type', 'Virtual Room', - required=True, track_visibility='always') + room_id = fields.Many2one('hotel.room.type', 'Virtual Room', + required=True, track_visibility='always') price = fields.Float('Price', default=0.0) date = fields.Date('Date', required=True, track_visibility='always') 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 91b28c8d4..712334ce8 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 @@ -199,7 +199,7 @@ var PMSCalendarController = AbstractController.extend({ this.model.get_room_types(), this.model.get_floors(), this.model.get_amenities(), - this.model.get_vrooms() + this.model.get_rooms() ).then(function(a1, a2, a3, a4){ self.renderer.loadViewFilters(a1, a2, a3, a4); }); 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 5f6297d73..63b254b84 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 @@ -80,7 +80,7 @@ return AbstractModel.extend({ context: Session.user_context, }); }, - get_vrooms: function() { + get_rooms: function() { return this._rpc({ model: 'hotel.room.type', method: 'search_read', diff --git a/hotel_calendar/views/actions.xml b/hotel_calendar/views/actions.xml index ea479919c..0f82b63e2 100644 --- a/hotel_calendar/views/actions.xml +++ b/hotel_calendar/views/actions.xml @@ -1,27 +1,27 @@ - - Hotel folio checkin - hotel.reservation - form - tree,form - [('is_checkin','=', True)] - + + Hotel folio checkin + hotel.reservation + form + tree,form + [('is_checkin','=', True)] + - - Hotel folio checkout - hotel.reservation - form - tree,form - [('is_checkout','=', True)] - + + Hotel folio checkout + hotel.reservation + form + tree,form + [('is_checkout','=', True)] + - - Virtual Room Pricelist Cached - virtual.room.pricelist.cached - form - tree,form - + + Room Pricelist Cached + room.pricelist.cached + form + tree,form + diff --git a/hotel_calendar/views/general.xml b/hotel_calendar/views/general.xml index 5b3ab3d38..c334b4286 100644 --- a/hotel_calendar/views/general.xml +++ b/hotel_calendar/views/general.xml @@ -1,32 +1,32 @@ - - + + - - diff --git a/hotel_calendar/views/inherited_hotel_room_type_views.xml b/hotel_calendar/views/inherited_hotel_room_type_views.xml new file mode 100644 index 000000000..71a877180 --- /dev/null +++ b/hotel_calendar/views/inherited_hotel_room_type_views.xml @@ -0,0 +1,14 @@ + + + + + hotel.room.type + + + + + + + + + diff --git a/hotel_calendar/views/inherited_hotel_room_views.xml b/hotel_calendar/views/inherited_hotel_room_views.xml index b5e45a354..c0198d112 100644 --- a/hotel_calendar/views/inherited_hotel_room_views.xml +++ b/hotel_calendar/views/inherited_hotel_room_views.xml @@ -1,13 +1,13 @@ - + hotel.room - - - + + + diff --git a/hotel_calendar/views/inherited_hotel_virtual_room_views.xml b/hotel_calendar/views/inherited_hotel_virtual_room_views.xml deleted file mode 100644 index 2d12dc572..000000000 --- a/hotel_calendar/views/inherited_hotel_virtual_room_views.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - hotel.room.type - - - - - - - - - diff --git a/hotel_calendar/views/inherited_res_users_views.xml b/hotel_calendar/views/inherited_res_users_views.xml index 3d3c18772..0d94cd57a 100644 --- a/hotel_calendar/views/inherited_res_users_views.xml +++ b/hotel_calendar/views/inherited_res_users_views.xml @@ -4,39 +4,39 @@ res.users - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hotel_calendar/views/room_pricelist_cached_views.xml b/hotel_calendar/views/room_pricelist_cached_views.xml new file mode 100644 index 000000000..0ed327c7c --- /dev/null +++ b/hotel_calendar/views/room_pricelist_cached_views.xml @@ -0,0 +1,34 @@ + + + + + + hotel.room.pricelist.cached.form + room.pricelist.cached + +
+ + + + + + + +
+
+
+ + + + hotel.room.pricelist.cached.tree + room.pricelist.cached + + + + + + + + + +
diff --git a/hotel_calendar/views/virtual_room_pricelist_cached_views.xml b/hotel_calendar/views/virtual_room_pricelist_cached_views.xml deleted file mode 100644 index 18e79643b..000000000 --- a/hotel_calendar/views/virtual_room_pricelist_cached_views.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - hotel.virtual.room.pricelist.cached.form - virtual.room.pricelist.cached - -
- - - - - - - -
-
-
- - - - hotel.virtual.room.pricelist.cached.tree - virtual.room.pricelist.cached - - - - - - - - - -
diff --git a/hotel_calendar_channel_connector/static/src/js/views/hotel_calendar_model.js b/hotel_calendar_channel_connector/static/src/js/views/hotel_calendar_model.js deleted file mode 100644 index 5f6297d73..000000000 --- a/hotel_calendar_channel_connector/static/src/js/views/hotel_calendar_model.js +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright 2018 Alexandre Díaz -// License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -odoo.define('hotel_calendar.PMSCalendarModel', function (require) { -"use strict"; - -var AbstractModel = require('web.AbstractModel'), - Context = require('web.Context'), - Core = require('web.core'), - FieldUtils = require('web.field_utils'), - Session = require('web.session'); - - -return AbstractModel.extend({ - init: function () { - this._super.apply(this, arguments); - this.end_date = null; - }, - - load: function (params) { - this.modelName = params.modelName; - this.modelManagementName = 'hotel.calendar.management' - }, - - save_pricelist: function(params) { - return this._rpc({ - model: this.modelManagementName, - method: 'save_changes', - args: params, - context: Session.user_context, - }); - }, - - swap_reservations: function(fromIds, toIds) { - return this._rpc({ - model: this.modelName, - method: 'swap_reservations', - args: [fromIds, toIds], - context: Session.user_context, - }); - }, - - get_calendar_data: function(oparams) { - return this._rpc({ - model: this.modelName, - method: 'get_hcalendar_all_data', - args: oparams, - context: Session.user_context, - }); - }, - - get_hcalendar_settings: function() { - return this._rpc({ - model: this.modelName, - method: 'get_hcalendar_settings', - args: [false], - }); - }, - - get_room_types: function() { - return this._rpc({ - model: 'hotel.room.type', - method: 'search_read', - args: [false, ['cat_id','name']], - context: Session.user_context, - }); - }, - get_floors: function() { - return this._rpc({ - model: 'hotel.floor', - method: 'search_read', - args: [false, ['id','name']], - context: Session.user_context, - }); - }, - get_amenities: function() { - return this._rpc({ - model: 'hotel.room.amenities', - method: 'search_read', - args: [false, ['id','name']], - context: Session.user_context, - }); - }, - get_vrooms: function() { - return this._rpc({ - model: 'hotel.room.type', - method: 'search_read', - args: [false, ['id','name']], - context: Session.user_context, - }); - }, - - search_count: function(domain) { - return this._rpc({ - model: this.modelName, - method: 'search_count', - args: [domain], - context: Session.user_context, - }); - }, - - update_records: function(ids, vals) { - return this._rpc({ - model: this.modelName, - method: 'write', - args: [ids, write_values], - context: Session.user_context, - }); - }, - - folio_search_count: function(domain) { - return this._rpc({ - model: 'hotel.folio', - method: 'search_count', - args: [domain], - context: Session.user_context, - }); - }, -}); -}); diff --git a/hotel_calendar_channel_connector/views/general.xml b/hotel_calendar_channel_connector/views/general.xml index e336595db..5d4e1f91f 100644 --- a/hotel_calendar_channel_connector/views/general.xml +++ b/hotel_calendar_channel_connector/views/general.xml @@ -1,12 +1,13 @@ - - + + diff --git a/hotel_channel_connector/components/importer.py b/hotel_channel_connector/components/importer.py index fb57c07e6..1b4c8c468 100644 --- a/hotel_channel_connector/components/importer.py +++ b/hotel_channel_connector/components/importer.py @@ -16,7 +16,7 @@ class HotelChannelConnectorImporter(AbstractComponent): _usage = 'channel.importer' @api.model - def _get_room_values_availability(self, vroom_id, date_str, day_vals, set_wmax_avail): + def _get_room_values_availability(self, vroom_id, date_str, day_vals, set_max_avail): virtual_room_avail_obj = self.env['hotel.virtual.room.availability'] vroom_avail = virtual_room_avail_obj.search([ ('virtual_room_id', '=', vroom_id), @@ -89,7 +89,7 @@ class HotelChannelConnectorImporter(AbstractComponent): }).create(vals) @api.model - def _generate_room_values(self, dfrom, dto, values, set_wmax_avail=False): + def _generate_room_values(self, dfrom, dto, values, set_max_avail=False): virtual_room_restr_obj = self.env['hotel.virtual.room.restriction'] hotel_virtual_room_obj = self.env['hotel.room.type'] def_restr_plan = virtual_room_restr_obj.search([('wpid', '=', '0')]) @@ -109,7 +109,7 @@ class HotelChannelConnectorImporter(AbstractComponent): vroom.id, date_str, day_vals, - set_wmax_avail) + set_max_avail) if def_restr_plan: self._get_room_values_restrictions( def_restr_plan.id, @@ -696,7 +696,7 @@ class HotelChannelConnectorImporter(AbstractComponent): @api.model def fetch_rooms_values(self, dfrom, dto, rooms=False, - set_wmax_avail=False): + set_max_avail=False): # Sanitize Dates now_dt = date_utils.now() dfrom_dt = date_utils.get_datetime(dfrom) @@ -715,8 +715,8 @@ class HotelChannelConnectorImporter(AbstractComponent): dfrom_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), dto_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), rooms) - self.generate_room_values(dfrom, dto, results, - set_wmax_avail=set_wmax_avail) + self._generate_room_values(dfrom, dto, results, + set_max_avail=set_max_avail) except ValidationError: self.create_issue('room', _("Can't fetch rooms values from WuBook"), results, dfrom=dfrom, dto=dto) diff --git a/hotel_channel_connector/wizard/wubook_import_availability.py b/hotel_channel_connector/wizard/wubook_import_availability.py index ce2b748cd..fad2af940 100644 --- a/hotel_channel_connector/wizard/wubook_import_availability.py +++ b/hotel_channel_connector/wizard/wubook_import_availability.py @@ -29,17 +29,15 @@ class ImportAvailabilityWizard(models.TransientModel): date_start = fields.Datetime('Start Date', required=True) date_end = fields.Datetime('End Date', required=True) - set_wmax_avail = fields.Boolean('Set wmax_avail?', default=True) + set_max_avail = fields.Boolean('Set max avail?', default=True) @api.multi def import_availability(self): for record in self: - date_start_dt = fields.Datetime.from_string(record.date_start) - date_end_dt = fields.Datetime.from_string(record.date_end) wres = self.env['wubook'].fetch_rooms_values( - date_start_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - date_end_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - set_wmax_avail=record.set_wmax_avail) + record.date_start, + record.date_end, + set_max_avail=record.set_max_avail) if not wres: raise ValidationError(_("Can't fetch availability from WuBook")) return True diff --git a/hotel_channel_connector/wubook.py b/hotel_channel_connector/wubook.py deleted file mode 100644 index ba7d97ec5..000000000 --- a/hotel_channel_connector/wubook.py +++ /dev/null @@ -1,1760 +0,0 @@ -# -*- coding: utf-8 -*- -############################################################################## -# -# OpenERP, Open Source Management Solution -# Copyright (C) 2017 Solucións Aloxa S.L. -# Alexandre Díaz -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -############################################################################## -import logging -import xmlrpc -import socket -import pytz -import json -from datetime import timedelta -from urllib.parse import urljoin -from odoo import models, api -from odoo.exceptions import UserError, ValidationError -from odoo.tools import ( - DEFAULT_SERVER_DATE_FORMAT, - DEFAULT_SERVER_DATETIME_FORMAT) -from odoo.addons.payment.models.payment_acquirer import _partner_split_name -from odoo.addons.hotel import date_utils -_logger = logging.getLogger(__name__) - -# GLOBAL VARS -DEFAULT_WUBOOK_DATE_FORMAT = "%d/%m/%Y" -DEFAULT_WUBOOK_TIME_FORMAT = "%H:%M" -DEFAULT_WUBOOK_DATETIME_FORMAT = "%s %s" % (DEFAULT_WUBOOK_DATE_FORMAT, - DEFAULT_WUBOOK_TIME_FORMAT) -WUBOOK_STATUS_CONFIRMED = 1 -WUBOOK_STATUS_WAITING = 2 -WUBOOK_STATUS_REFUSED = 3 -WUBOOK_STATUS_ACCEPTED = 4 -WUBOOK_STATUS_CANCELLED = 5 -WUBOOK_STATUS_CANCELLED_PENALTY = 6 - -WUBOOK_STATUS_GOOD = ( - WUBOOK_STATUS_CONFIRMED, - WUBOOK_STATUS_WAITING, - WUBOOK_STATUS_ACCEPTED, -) -WUBOOK_STATUS_BAD = ( - WUBOOK_STATUS_REFUSED, - WUBOOK_STATUS_CANCELLED, - WUBOOK_STATUS_CANCELLED_PENALTY, -) - -# class TimeoutTransport(xmlrpclib.Transport): -# """ -# Custom XML-RPC transport class for HTTP connections, allowing a timeout in -# the base connection. -# """ -# -# def __init__(self, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, use_datetime=0): -# xmlrpclib.Transport.__init__(self, use_datetime) -# self._timeout = timeout -# -# def make_connection(self, host): -# # If using python 2.6, since that implementation normally returns the -# # HTTP compatibility class, which doesn't have a timeout feature. -# #import httplib -# #host, extra_headers, x509 = self.get_host_info(host) -# #return httplib.HTTPConnection(host, timeout=self._timeout) -# -# conn = xmlrpclib.Transport.make_connection(self, host) -# conn.timeout = self._timeout -# return conn - - -# WUBOOK -class WuBook(models.AbstractModel): - _name = 'wubook' - - # === INITALIZATION - def __init__(self, pool, cr): - super(WuBook, self).__init__(pool, cr) - self.SERVER = False - self.LCODE = False - self.TOKEN = False - - @api.model - def initialize(self, activate): - self_context = self.with_context({'init_connection': False}) - if not self_context.init_connection(): - return False - if activate: - if not self_context.push_activation(): - return False - - res = (self_context.import_rooms()[0] - and self_context.import_channels_info()[0] - and self_context.import_pricing_plans()[0] - and self_context.import_restriction_plans()[0]) - - self_context.close_connection() - return res - - @api.model - def push_activation(self): - base_url = self.env['ir.config_parameter'].get_param('web.base.url') - base_url = base_url.replace("http://", "https://") - hotel_security_token = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_push_security_token') - - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode_a, results_a = self.SERVER.push_activation( - self.TOKEN, - self.LCODE, - urljoin(base_url, - "/wubook/push/reservations/%s" % hotel_security_token), - 1) - rcode_ua, results_ua = self.SERVER.push_update_activation( - self.TOKEN, - self.LCODE, - urljoin(base_url, "/wubook/push/rooms/%s" % hotel_security_token)) - if init_connection: - self.close_connection() - - if rcode_a != 0: - self.create_wubook_issue('wubook', - "Can't activate push reservations", - results_a) - if rcode_ua != 0: - self.create_wubook_issue('wubook', "Can't activate push rooms", - results_ua) - - return rcode_a == 0 and rcode_ua == 0 - - def is_valid_account(self): - user = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_user') - passwd = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_passwd') - lcode = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_lcode') - pkey = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_pkey') - server_addr = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_server') - return bool(user and passwd and pkey and server_addr and lcode) - - # === NETWORK - def init_connection(self): - user = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_user') - passwd = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_passwd') - self.LCODE = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_lcode') - pkey = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_pkey') - server_addr = self.env['ir.default'].sudo().get( - 'wubook.config.settings', 'wubook_server') - - if not user or not passwd or not pkey or not server_addr or \ - not self.LCODE: - self.create_wubook_issue( - 'wubook', - "Can't connect with WuBook! Perhaps account not configured...", - "") - return False - - try: - # t = TimeoutTransport(timeout=3) - # self.SERVER = xmlrpclib.Server(server_addr, transport=t) - self.SERVER = xmlrpclib.Server(server_addr) - res, tok = self.SERVER.acquire_token(user, passwd, pkey) - self.TOKEN = tok - if res != 0: - self.create_wubook_issue( - 'wubook', - "Can't connect with WuBook! Perhaps the account haven't \ - a good configuration...", - tok) - except Exception: - self.create_wubook_issue( - 'wubook', - "Can't connect with WuBook! Please, check internet \ - connection.", - "") - res = -1 - - return res == 0 - - def close_connection(self): - self.SERVER.release_token(self.TOKEN) - self.TOKEN = False - self.SERVER = False - - # === HELPER FUNCTIONS - @api.model - def create_wubook_issue(self, section, message, wmessage, wid=False, - dfrom=False, dto=False): - self.env['wubook.issue'].sudo().create({ - 'section': section, - 'message': message, - 'wid': wid, - 'wmessage': wmessage, - 'date_start': dfrom and date_utils.get_datetime( - dfrom, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT).strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'date_end': dto and date_utils.get_datetime( - dto, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT).strftime( - DEFAULT_SERVER_DATE_FORMAT), - }) - - def set_clousure_today(self, status): - hotel_tz = self.env['ir.default'].sudo().get('hotel.config.settings', - 'tz_hotel') - now_utc_dt = date_utils.now() - now_dt = date_utils.dt_as_timezone(now_utc_dt, hotel_tz) - now_str = now_dt.strftime(DEFAULT_SERVER_DATE_FORMAT) - vrooms = self.env['hotel.virtual.room'].search([]) - - restriction_parity_id = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'parity_restrictions_id') - if restriction_parity_id: - restriction_parity_id = int(restriction_parity_id) - - vroom_restr_obj = self.env['hotel.virtual.room.restriction.item'] - vroom_obj = self.env['hotel.virtual.room'] - - vrooms = vroom_obj.search([('wrid', '!=', False), ('wrid', '!=', '')]) - for vroom in vrooms: - restr = vroom_restr_obj.search([ - ('restriction_id', '=', restriction_parity_id), - ('virtual_room_id', '=', vroom.id), - ('date_start', '>=', now_str), - ('date_end', '<=', now_str), - ('applied_on', '=', '0_virtual_room'), - ], limit=1) - if restr: - restr.write({'closed': status}) - else: - restr = vroom_restr_obj.create({ - 'date_start': now_str, - 'date_end': now_str, - 'virtual_room_id': vroom.id, - 'applied_on': '0_virtual_room', - 'restriction_id': restriction_parity_id, - 'min_stay': 0, - 'min_stay_arrival': 0, - 'max_stay': 0, - 'max_stay_arrival': 0, - 'closed': status, - 'closed_departure': False, - 'closed_arrival': False, - 'wpushed': False, - }) - if not restr: - raise ValidationError("Can't close rooms!") - return self.push_restrictions() - - # === ROOMS - @api.model - def create_room(self, shortcode, name, capacity, price, availability): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.new_room( - self.TOKEN, - self.LCODE, - 0, - name, - capacity, - price, - availability, - shortcode[:4], - 'nb' # TODO: Complete this part - # rtype=('name' in vals and vals['name'] and 3) or 1 - ) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'room', "Can't create room in WuBook", results) - return False - - return results - - @api.model - def modify_room(self, wrid, name, capacity, price, availability, scode): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.mod_room( - self.TOKEN, - self.LCODE, - wrid, - name, - capacity, - price, - availability, - scode, - 'nb' - # rtype=('name' in vals and vals['name'] and 3) or 1 - ) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('room', "Can't modify room in WuBook", - results, wid=wrid) - - return rcode == 0 - - @api.model - def delete_room(self, wrid): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.del_room( - self.TOKEN, - self.LCODE, - wrid - ) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('room', "Can't delete room in WuBook", - results, wid=wrid) - - return rcode == 0 - - @api.model - def import_rooms(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - rcode, results = self.SERVER.fetch_rooms( - self.TOKEN, - self.LCODE, - 0 - ) - if init_connection: - self.close_connection() - - vroom_obj = self.env['hotel.virtual.room'] - count = 0 - if rcode == 0: - count = len(results) - for room in results: - vroom = vroom_obj.search([('wrid', '=', room['id'])], limit=1) - vals = { - 'name': room['name'], - 'wrid': room['id'], - 'wscode': room['shortname'], - 'list_price': room['price'], - 'wcapacity': room['occupancy'], - # 'max_real_rooms': room['availability'], - } - if vroom: - vroom.with_context({'wubook_action': False}).write(vals) - else: - vroom_obj.with_context({'wubook_action': False}).create( - vals) - else: - self.create_wubook_issue( - 'room', "Can't import rooms from WuBook", results) - - return (rcode == 0, count) - - @api.model - def fetch_rooms_values(self, dfrom, dto, rooms=False, - set_wmax_avail=False): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - # Sanitize Dates - now_dt = date_utils.now() - now = now_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT) - dfrom_dt = date_utils.get_datetime(dfrom, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - dto_dt = date_utils.get_datetime(dto, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - if dto_dt < now_dt: - return True - if dfrom_dt < now_dt: - dfrom = now - if dfrom_dt > dto_dt: - dtemp = dfrom - dfrom = dto - dto = dtemp - rcode, results = self.SERVER.fetch_rooms_values(self.TOKEN, - self.LCODE, - dfrom, - dto, - rooms) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('room', - "Can't fetch rooms values from WuBook", - results, dfrom=dfrom, dto=dto) - else: - self.generate_room_values(dfrom, dto, results, - set_wmax_avail=set_wmax_avail) - - return rcode == 0 - - @api.model - def update_availability(self, rooms_avail): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.update_sparse_avail(self.TOKEN, - self.LCODE, - rooms_avail) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'room', - "Can't update rooms availability in WuBook", - results) - - return rcode == 0 - - @api.model - def corporate_fetch(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.corporate_fetchable_properties(self.TOKEN) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'wubook', - "Can't call 'corporate_fetch' from WuBook", - results) - - return rcode == 0 - - # === RESERVATIONS - @api.model - def create_reservation(self, reserv): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - vroom = self.env['hotel.virtual.room'].search([ - ('product_id', '=', reserv.product_id.id) - ], limit=1) - customer = { - 'lname': _partner_split_name(reserv.partner_id.name)[0], - 'fname': _partner_split_name(reserv.partner_id.name)[1], - 'email': reserv.partner_id.email, - 'city': reserv.partner_id.city, - 'phone': reserv.partner_id.phone, - 'street': reserv.partner_id.street, - 'country': reserv.partner_id.country_id.code, - 'arrival_hour': date_utils.get_datetime(reserv.checkin, - dtformar="%H:%M:%S"), - 'notes': '' # TODO: - } - rcode, results = self.SERVER.new_reservation( - self.TOKEN, - self.LCODE, - reserv.checkin, - reserv.checkout, - {vroom.wrid: [reserv.adults+reserv.children, 'nb']}, - customer, - reserv.adults+reserv.children) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('reservation', - "Can't create reservations in wubook", - results, - dfrom=reserv.checkin, dto=reserv.checkout) - else: - reserv.write({'wrid': results}) - - return rcode == 0 - - @api.model - def cancel_reservation(self, wrid, reason=""): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.cancel_reservation(self.TOKEN, - self.LCODE, - wrid, - reason) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('reservation', - "Can't cancel reservation in WuBook", - results, wid=wrid) - - return rcode == 0 - - @api.model - def fetch_new_bookings(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - rcode, results = self.SERVER.fetch_new_bookings(self.TOKEN, - self.LCODE, - 1, - 0) - errors = False - processed_rids = [] - if rcode == 0: - processed_rids, errors, checkin_utc_dt, checkout_utc_dt = \ - self.generate_reservations(results) - if any(processed_rids): - uniq_rids = list(set(processed_rids)) - rcodeb, resultsb = self.SERVER.mark_bookings(self.TOKEN, - self.LCODE, - uniq_rids) - - if rcodeb != 0: - self.create_wubook_issue( - 'wubook', - "Problem trying mark bookings (%s)" % - str(processed_rids), - '') - if init_connection: - self.close_connection() - - # Update Odoo availability (don't wait for wubook) - if rcode == 0 and checkin_utc_dt and checkout_utc_dt: - self.fetch_rooms_values( - checkin_utc_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - checkout_utc_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT)) - - if rcode != 0: - self.create_wubook_issue('reservation', - "Can't process reservations from wubook", - results) - - return ((rcode == 0 and not errors), len(processed_rids)) - - @api.model - def fetch_booking(self, lcode, wrid): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - rcode, results = self.SERVER.fetch_booking(self.TOKEN, - lcode, - wrid) - errors = False - processed_rids = [] - if rcode == 0: - processed_rids, errors, checkin_utc_dt, checkout_utc_dt = \ - self.generate_reservations(results) - if any(processed_rids): - uniq_rids = list(set(processed_rids)) - rcode, results = self.SERVER.mark_bookings(self.TOKEN, - self.LCODE, - uniq_rids) - - if rcode != 0: - self.create_wubook_issue( - 'wubook', - "Problem trying mark bookings (%s)" % - str(processed_rids), - '') - - if init_connection: - self.close_connection() - - # Update Odoo availability (don't wait for wubook) - if rcode == 0 and checkin_utc_dt and checkout_utc_dt: - self.fetch_rooms_values( - checkin_utc_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - checkout_utc_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT)) - - if rcode != 0: - self.create_wubook_issue('reservation', - "Can't process reservations from wubook", - results, wid=wrid) - - return ((rcode == 0 and not errors), len(processed_rids)) - - @api.model - def mark_bookings(self, wrids): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.mark_bookings(self.TOKEN, - self.LCODE, - wrids) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'reservation', - "Can't mark as readed a reservation in wubook", - results, wid=str(wrids)) - - return rcode == 0 - - # === PRICE PLANS - @api.model - def create_plan(self, name, daily=1): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.add_pricing_plan(self.TOKEN, - self.LCODE, - name, - daily) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'plan', "Can't add pricing plan to wubook", results) - return False - - return results - - @api.model - def delete_plan(self, pid): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.del_plan(self.TOKEN, - self.LCODE, - pid) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('plan', - "Can't delete pricing plan from wubook", - results, - wid=pid) - - return rcode == 0 - - @api.model - def update_plan_name(self, pid, name): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.update_plan_name(self.TOKEN, - self.LCODE, - pid, - name) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't update pricing plan name in wubook", - results, wid=pid) - - return rcode == 0 - - @api.model - def update_plan_prices(self, pid, dfrom, prices): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.update_plan_prices(self.TOKEN, - self.LCODE, - pid, - dfrom, - prices) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't update pricing plan in wubook", - results, wid=pid, dfrom=dfrom) - - return rcode == 0 - - @api.model - def update_plan_periods(self, pid, periods): - _logger.info("[WuBook] Updating Plan Periods...") - _logger.info(periods) - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.update_plan_periods(self.TOKEN, - self.LCODE, - pid, - periods) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't update pricing plan period in wubook", - results, wid=pid) - - return rcode == 0 - - @api.model - def import_pricing_plans(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - rcode, results = self.SERVER.get_pricing_plans(self.TOKEN, - self.LCODE) - if init_connection: - self.close_connection() - - count = 0 - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't get pricing plans from wubook", - results) - else: - count = self.generate_pricelists(results) - - return (rcode == 0, count) - - @api.model - def fetch_plan_prices(self, pid, dfrom, dto, rooms=None): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.fetch_plan_prices(self.TOKEN, - self.LCODE, - pid, - dfrom, - dto, - rooms or []) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't fetch plan prices from wubook", - results, wid=pid, dfrom=dfrom, dto=dto) - else: - self.generate_pricelist_items(pid, dfrom, dto, results) - - return rcode == 0 - - @api.model - def fetch_all_plan_prices(self, dfrom, dto, rooms=None): - no_errors = True - plan_wpids = self.env['product.pricelist'].search([ - ('wpid', '!=', False), ('wpid', '!=', '') - ]).mapped('wpid') - if any(plan_wpids): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - for wpid in plan_wpids: - rcode, results = self.SERVER.fetch_plan_prices(self.TOKEN, - self.LCODE, - wpid, - dfrom, - dto, - rooms or []) - if rcode != 0: - self.create_wubook_issue( - 'plan', - "Can't fetch all plan prices from wubook!", - results, wid=wpid, dfrom=dfrom, dto=dto) - no_errors = False - else: - self.generate_pricelist_items(wpid, dfrom, dto, results) - if init_connection: - self.close_connection() - - return no_errors - - # === RESTRICTION PLANS - @api.model - def import_restriction_plans(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - rcode, results = self.SERVER.rplan_rplans(self.TOKEN, - self.LCODE) - if init_connection: - self.close_connection() - - count = 0 - if rcode != 0: - self.create_wubook_issue( - 'rplan', - "Can't fetch restriction plans from wubook", - results) - else: - count = self.generate_restrictions(results) - - return (rcode == 0, count) - - @api.model - def fetch_rplan_restrictions(self, dfrom, dto, rpid=False): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.wired_rplan_get_rplan_values(self.TOKEN, - self.LCODE, - dfrom, - dto, - int(rpid)) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'rplan', - "Can't fetch plan restrictions from wubook", - results, wid=rpid, dfrom=dfrom, dto=dto) - elif any(results): - self.generate_restriction_items(dfrom, dto, results) - - return rcode == 0 - - @api.model - def update_rplan_values(self, rpid, dfrom, values): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.rplan_update_rplan_values(self.TOKEN, - self.LCODE, - rpid, - dfrom, - values) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue( - 'rplan', - "Can't update plan restrictions on wubook", - results, wid=rpid, dfrom=dfrom) - - return rcode == 0 - - @api.model - def create_rplan(self, name, compact=False): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.rplan_add_rplan(self.TOKEN, - self.LCODE, - name, - compact and 1 or 0) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('rplan', - "Can't create plan restriction in wubook", - results) - return False - - return results - - @api.model - def rename_rplan(self, rpid, name): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.rplan_rename_rplan(self.TOKEN, - self.LCODE, - rpid, - name) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('rplan', - "Can't rename plan restriction in wubook", - results, wid=rpid) - - return rcode == 0 - - @api.model - def delete_rplan(self, rpid): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return False - rcode, results = self.SERVER.rplan_del_rplan(self.TOKEN, - self.LCODE, - rpid) - if init_connection: - self.close_connection() - - if rcode != 0: - self.create_wubook_issue('rplan', - "Can't delete plan restriction on wubook", - results, wid=rpid) - - return rcode == 0 - - # === WUBOOK INFO - @api.model - def import_channels_info(self): - init_connection = self._context.get('init_connection', True) - if init_connection: - if not self.init_connection(): - return (False, 0) - results = self.SERVER.get_channels_info(self.TOKEN) - if init_connection: - self.close_connection() - - count = self.generate_wubook_channel_info(results) - - return (True, count) - - # === WUBOOK -> ODOO - @api.model - def generate_room_values(self, dfrom, dto, values, set_wmax_avail=False): - virtual_room_avail_obj = self.env['hotel.virtual.room.availability'] - virtual_room_restr_obj = self.env['hotel.virtual.room.restriction'] - vroom_restr_item_obj = self.env['hotel.virtual.room.restriction.item'] - hotel_virtual_room_obj = self.env['hotel.virtual.room'] - def_wubook_restr = virtual_room_restr_obj.search([('wpid', '=', '0')]) - _logger.info("==== ROOM VALUES (%s -- %s)", dfrom, dto) - _logger.info(values) - for k_rid, v_rid in values.iteritems(): - vroom = hotel_virtual_room_obj.search([ - ('wrid', '=', k_rid) - ], limit=1) - if vroom: - date_dt = date_utils.get_datetime( - dfrom, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - for day_vals in v_rid: - date_str = date_dt.strftime(DEFAULT_SERVER_DATE_FORMAT) - # Get Availability - vroom_avail = virtual_room_avail_obj.search([ - ('virtual_room_id', '=', vroom.id), - ('date', '=', date_str) - ], limit=1) - vals = { - 'no_ota': day_vals.get('no_ota'), - 'booked': day_vals.get('booked'), - 'avail': day_vals.get('avail', 0), - 'wpushed': True, - } - if set_wmax_avail: - vals.update({'wmax_avail': day_vals.get('avail', 0)}) - if vroom_avail: - vroom_avail.with_context({ - 'wubook_action': False, - }).write(vals) - else: - vals.update({ - 'virtual_room_id': vroom.id, - 'date': date_str, - }) - virtual_room_avail_obj.with_context({ - 'wubook_action': False, - 'mail_create_nosubscribe': True, - }).create(vals) - - # Get Restrictions - if def_wubook_restr: - vroom_restr = vroom_restr_item_obj.search([ - ('virtual_room_id', '=', vroom.id), - ('applied_on', '=', '0_virtual_room'), - ('date_start', '=', date_str), - ('date_end', '=', date_str), - ('restriction_id', '=', def_wubook_restr.id), - ]) - vals = { - 'min_stay': int(day_vals.get('min_stay', 0)), - 'min_stay_arrival': int(day_vals.get( - 'min_stay_arrival', - 0)), - 'max_stay': int(day_vals.get('max_stay', 0)), - 'max_stay_arrival': int(day_vals.get( - 'max_stay_arrival', - 0)), - 'closed': int(day_vals.get('closed', False)), - 'closed_departure': int(day_vals.get( - 'closed_departure', - False)), - 'closed_arrival': int(day_vals.get( - 'closed_arrival', - False)), - 'wpushed': True, - } - if vroom_restr: - vroom_restr.with_context({ - 'wubook_action': False, - }).write(vals) - else: - vals.update({ - 'restriction_id': def_wubook_restr.id, - 'virtual_room_id': vroom.id, - 'date_start': date_str, - 'date_end': date_str, - 'applied_on': '0_virtual_room', - }) - vroom_restr_item_obj.with_context({ - 'wubook_action': False, - }).create(vals) - date_dt = date_dt + timedelta(days=1) - return True - - @api.model - def generate_restrictions(self, restriction_plans): - restriction_obj = self.env['hotel.virtual.room.restriction'] - count = 0 - for plan in restriction_plans: - vals = { - 'name': plan['name'], - } - plan_id = restriction_obj.search([ - ('wpid', '=', str(plan['id'])) - ], limit=1) - if not plan_id: - vals.update({ - 'wpid': str(plan['id']), - }) - restriction_obj.with_context({ - 'wubook_action': False, - 'rules': plan.get('rules'), - }).create(vals) - else: - plan_id.with_context({'wubook_action': False}).write(vals) - count = count + 1 - return count - - @api.model - def generate_restriction_items(self, dfrom, dto, plan_restrictions): - hotel_virtual_room_obj = self.env['hotel.virtual.room'] - reserv_restriction_obj = self.env['hotel.virtual.room.restriction'] - restriction_item_obj = self.env['hotel.virtual.room.restriction.item'] - _logger.info("===== RESTRICTIONS") - _logger.info(plan_restrictions) - for k_rpid, v_rpid in plan_restrictions.iteritems(): - restriction_id = reserv_restriction_obj.search([ - ('wpid', '=', k_rpid) - ], limit=1) - if restriction_id: - for k_rid, v_rid in v_rpid.iteritems(): - vroom = hotel_virtual_room_obj.search([ - ('wrid', '=', k_rid) - ], limit=1) - if vroom: - for item in v_rid: - date_dt = date_utils.get_datetime( - item['date'], - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - restriction_item = restriction_item_obj.search([ - ('restriction_id', '=', restriction_id.id), - ('date_start', '=', date_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT)), - ('date_end', '=', date_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT)), - ('applied_on', '=', '0_virtual_room'), - ('virtual_room_id', '=', vroom.id) - ], limit=1) - vals = { - 'closed_arrival': item['closed_arrival'], - 'closed': item['closed'], - 'min_stay': item['min_stay'], - 'closed_departure': item['closed_departure'], - 'max_stay': item['max_stay'], - 'max_stay_arrival': item['max_stay_arrival'], - 'min_stay_arrival': item['min_stay_arrival'], - 'wpushed': True, - } - if restriction_item: - restriction_item.with_context({ - 'wubook_action': False}).write(vals) - else: - vals.update({ - 'restriction_id': restriction_id.id, - 'date_start': date_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'date_end': date_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'applied_on': '0_virtual_room', - 'virtual_room_id': vroom.id - }) - restriction_item_obj.with_context({ - 'wubook_action': False}).create(vals) - - return True - - @api.model - def generate_pricelist_items(self, pid, dfrom, dto, plan_prices): - hotel_virtual_room_obj = self.env['hotel.virtual.room'] - pricelist = self.env['product.pricelist'].search([ - ('wpid', '=', pid) - ], limit=1) - if pricelist: - pricelist_item_obj = self.env['product.pricelist.item'] - dfrom_dt = date_utils.get_datetime( - dfrom, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - dto_dt = date_utils.get_datetime( - dto, - dtformat=DEFAULT_WUBOOK_DATE_FORMAT) - days_diff = date_utils.date_diff(dfrom_dt, dto_dt, hours=False) + 1 - for i in range(0, days_diff): - ndate_dt = dfrom_dt + timedelta(days=i) - for k_rid, v_rid in plan_prices.iteritems(): - vroom = hotel_virtual_room_obj.search([ - ('wrid', '=', k_rid) - ], limit=1) - if vroom: - pricelist_item = pricelist_item_obj.search([ - ('pricelist_id', '=', pricelist.id), - ('date_start', '=', ndate_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT)), - ('date_end', '=', ndate_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT)), - ('compute_price', '=', 'fixed'), - ('applied_on', '=', '1_product'), - ('product_tmpl_id', '=', vroom.product_id.product_tmpl_id.id) - ], limit=1) - vals = { - 'fixed_price': plan_prices[k_rid][i], - 'wpushed': True, - } - if pricelist_item: - pricelist_item.with_context({ - 'wubook_action': False}).write(vals) - else: - vals.update({ - 'pricelist_id': pricelist.id, - 'date_start': ndate_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'date_end': ndate_dt.strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'compute_price': 'fixed', - 'applied_on': '1_product', - 'product_tmpl_id': vroom.product_id.product_tmpl_id.id - }) - pricelist_item_obj.with_context({ - 'wubook_action': False}).create(vals) - return True - - @api.model - def generate_pricelists(self, price_plans): - product_listprice_obj = self.env['product.pricelist'] - count = 0 - for plan in price_plans: - if 'vpid' in plan: - continue # Ignore Virtual Plans - - vals = { - 'name': plan['name'], - 'wdaily': plan['daily'] == 1, - } - plan_id = product_listprice_obj.search([ - ('wpid', '=', str(plan['id'])) - ], limit=1) - if not plan_id: - vals.update({ - 'wpid': str(plan['id']), - }) - product_listprice_obj.with_context({ - 'wubook_action': False}).create(vals) - else: - plan_id.with_context({'wubook_action': False}).write(vals) - count = count + 1 - return count - - @api.model - def _generate_booking_vals(self, broom, checkin_str, checkout_str, - is_cancellation, wchannel_info, wstatus, crcode, - rcode, vroom, split_booking, dates_checkin, - dates_checkout, book): - # Generate Reservation Day Lines - reservation_line_ids = [] - tprice = 0.0 - for brday in broom['roomdays']: - wndate = date_utils.get_datetime( - brday['day'], - dtformat=DEFAULT_WUBOOK_DATE_FORMAT - ).replace(tzinfo=pytz.utc) - if date_utils.date_in(wndate, - dates_checkin[0], - dates_checkout[0] - timedelta(days=1), - hours=False) == 0: - reservation_line_ids.append((0, False, { - 'date': wndate.strftime( - DEFAULT_SERVER_DATE_FORMAT), - 'price': brday['price'] - })) - tprice += brday['price'] - persons = vroom.wcapacity - if 'ancillary' in broom and 'guests' in broom['ancillary']: - persons = broom['ancillary']['guests'] - vals = { - 'checkin': checkin_str, - 'checkout': checkout_str, - 'adults': persons, - 'children': book['children'], - 'reservation_line_ids': reservation_line_ids, - 'price_unit': tprice, - 'to_assign': True, - 'wrid': rcode, - 'wchannel_id': wchannel_info and wchannel_info.id, - 'wchannel_reservation_code': crcode, - 'wstatus': wstatus, - 'to_read': True, - 'state': is_cancellation and 'cancelled' or 'draft', - 'virtual_room_id': vroom.id, - 'splitted': split_booking, - 'wbook_json': json.dumps(book), - 'wmodified': book['was_modified'] - } - _logger.info("===== CONTRUCT RESERV") - _logger.info(vals) - return vals - - @api.model - def _generate_partner_vals(self, book): - country_id = self.env['res.country'].search([ - ('code', '=', str(book['customer_country'])) - ], limit=1) - # lang = self.env['res.lang'].search([('code', '=', book['customer_language_iso'])], limit=1) - return { - 'name': "%s, %s" % - (book['customer_surname'], book['customer_name']), - 'country_id': country_id and country_id.id, - 'city': book['customer_city'], - 'phone': book['customer_phone'], - 'zip': book['customer_zip'], - 'street': book['customer_address'], - 'email': book['customer_mail'], - 'unconfirmed': True, - # 'lang': lang and lang.id, - } - - # FIXME: Super big method!!! O_o - @api.model - def generate_reservations(self, bookings): - _logger.info("=== BOOKINGS FROM WUBOOK") - _logger.info(bookings) - default_arrival_hour = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'default_arrival_hour') - default_departure_hour = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'default_departure_hour') - - # Get user timezone - tz_hotel = self.env['ir.default'].sudo().get( - 'hotel.config.settings', 'tz_hotel') - res_partner_obj = self.env['res.partner'] - hotel_reserv_obj = self.env['hotel.reservation'] - hotel_folio_obj = self.env['hotel.folio'] - hotel_vroom_obj = self.env['hotel.virtual.room'] - # Space for store some data for construct folios - processed_rids = [] - failed_reservations = [] - checkin_utc_dt = False - checkout_utc_dt = False - split_booking = False - for book in bookings: # This create a new folio - splitted_map = {} - is_cancellation = book['status'] in WUBOOK_STATUS_BAD - bstatus = str(book['status']) - rcode = str(book['reservation_code']) - crcode = str(book['channel_reservation_code']) \ - if book['channel_reservation_code'] else 'undefined' - - # Can't process failed reservations - # (for example set a invalid new reservation and receive in - # the same transaction an cancellation) - if crcode in failed_reservations: - self.create_wubook_issue( - 'reservation', - "Can't process a reservation that previusly failed!", - '', wid=book['reservation_code']) - continue - - # Get dates for the reservation (GMT->UTC) - arr_hour = default_arrival_hour if book['arrival_hour'] == "--" \ - else book['arrival_hour'] - checkin = "%s %s" % (book['date_arrival'], arr_hour) - checkin_dt = date_utils.get_datetime( - checkin, - dtformat=DEFAULT_WUBOOK_DATETIME_FORMAT, - stz=tz_hotel) - checkin_utc_dt = date_utils.dt_as_timezone(checkin_dt, 'UTC') - checkin = checkin_utc_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT) - - checkout = "%s %s" % (book['date_departure'], - default_departure_hour) - checkout_dt = date_utils.get_datetime( - checkout, - dtformat=DEFAULT_WUBOOK_DATETIME_FORMAT, - stz=tz_hotel) - checkout_utc_dt = date_utils.dt_as_timezone(checkout_dt, 'UTC') - checkout = checkout_utc_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT) - - # Search Folio. If exists. - folio_id = False - if crcode != 'undefined': - reserv_folio = hotel_reserv_obj.search([ - ('wchannel_reservation_code', '=', crcode) - ], limit=1) - if reserv_folio: - folio_id = reserv_folio.folio_id - else: - reserv_folio = hotel_reserv_obj.search([ - ('wrid', '=', rcode) - ], limit=1) - if reserv_folio: - folio_id = reserv_folio.folio_id - - # Need update reservations? - sreservs = hotel_reserv_obj.search([('wrid', '=', rcode)]) - reservs = folio_id.room_lines if folio_id else sreservs - reservs_processed = False - if any(reservs): - folio_id = reservs[0].folio_id - for reserv in reservs: - if reserv.wrid == rcode: - reserv.with_context({'wubook_action': False}).write({ - 'wstatus': str(book['status']), - 'wstatus_reason': book.get('status_reason', ''), - 'to_read': True, - 'to_assign': True, - 'price_unit': book['amount'], - 'wcustomer_notes': book['customer_notes'], - 'wbook_json': json.dumps(book), - }) - if reserv.partner_id.unconfirmed: - reserv.partner_id.write( - self._generate_partner_vals(book) - ) - reservs_processed = True - if is_cancellation: - reserv.with_context({ - 'wubook_action': False}).action_cancel() - elif reserv.state == 'cancelled': - reserv.with_context({ - 'wubook_action': False, - }).write({ - 'discount': 0.0, - 'state': 'confirm', - }) - - # Do Nothing if already processed 'wrid' - if reservs_processed: - processed_rids.append(rcode) - continue - - # Search Customer - customer_mail = book.get('customer_mail', False) - partner_id = False - if customer_mail: - partner_id = res_partner_obj.search([ - ('email', '=', customer_mail) - ], limit=1) - if not partner_id: - partner_id = res_partner_obj.create(self._generate_partner_vals(book)) - - # Search Wubook Channel Info - wchannel_info = self.env['wubook.channel.info'].search( - [('wid', '=', str(book['id_channel']))], limit=1) - - reservations = [] - used_rooms = [] - # Iterate booked rooms - for broom in book['booked_rooms']: - vroom = hotel_vroom_obj.search([ - ('wrid', '=', broom['room_id']) - ], limit=1) - if not vroom: - self.create_wubook_issue( - 'reservation', - "Can't found any virtual room associated to '%s' \ - in this hotel" % book['rooms'], - '', wid=book['reservation_code']) - failed_reservations.append(crcode) - continue - - dates_checkin = [checkin_utc_dt, False] - dates_checkout = [checkout_utc_dt, False] - split_booking = False - split_booking_parent = False - # This perhaps create splitted reservation - while dates_checkin[0]: - checkin_str = dates_checkin[0].strftime( - DEFAULT_SERVER_DATETIME_FORMAT) - checkout_str = dates_checkout[0].strftime( - DEFAULT_SERVER_DATETIME_FORMAT) - vals = self._generate_booking_vals( - broom, - checkin_str, - checkout_str, - is_cancellation, - wchannel_info, - bstatus, - crcode, - rcode, - vroom, - split_booking, - dates_checkin, - dates_checkout, - book, - ) - if vals['price_unit'] != book['amount']: - self.create_wubook_issue( - 'reservation', - "Invalid reservation total price! %.2f != %.2f" % (vals['price_unit'], book['amount']), - '', wid=book['reservation_code']) - - free_rooms = hotel_vroom_obj.check_availability_virtual_room( - checkin_str, - checkout_str, - virtual_room_id=vroom.id, - notthis=used_rooms) - if any(free_rooms): - vals.update({ - 'product_id': free_rooms[0].product_id.id, - 'name': free_rooms[0].name, - }) - reservations.append((0, False, vals)) - used_rooms.append(free_rooms[0].id) - - if split_booking: - if not split_booking_parent: - split_booking_parent = len(reservations) - else: - splitted_map.setdefault( - split_booking_parent, - []).append(len(reservations)) - dates_checkin = [dates_checkin[1], False] - dates_checkout = [dates_checkout[1], False] - else: - date_diff = (dates_checkout[0].replace( - hour=0, minute=0, second=0, - microsecond=0) - - dates_checkin[0].replace( - hour=0, minute=0, second=0, - microsecond=0)).days - if date_diff <= 0: - if split_booking: - if split_booking_parent: - del reservations[split_booking_parent-1:] - if split_booking_parent in splitted_map: - del splitted_map[split_booking_parent] - # Can't found space for reservation - vals = self._generate_booking_vals( - broom, - checkin_utc_dt, - checkout_utc_dt, - is_cancellation, - wchannel_info, - bstatus, - crcode, - rcode, - vroom, - False, - (checkin_utc_dt, False), - (checkout_utc_dt, False), - book, - ) - vals.update({ - 'product_id': - vroom.room_ids[0].product_id.id, - 'name': vroom.name, - 'overbooking': True, - }) - reservations.append((0, False, vals)) - self.create_wubook_issue( - 'reservation', - "Reservation imported with overbooking state", - '', wid=rcode) - dates_checkin = [False, False] - dates_checkout = [False, False] - split_booking = False - else: - split_booking = True - dates_checkin = [ - dates_checkin[0], - dates_checkin[0] + timedelta(days=date_diff-1) - ] - dates_checkout = [ - dates_checkout[0] - timedelta(days=1), - checkout_utc_dt - ] - - if split_booking: - self.create_wubook_issue( - 'reservation', - "Reservation Splitted", - '', wid=rcode) - - # Create Folio - if not any(failed_reservations) and any(reservations): - try: - # TODO: Improve 'addons_list' & discounts - addons = str(book['addons_list']) if any(book['addons_list']) else '' - discounts = book.get('discount', '') - vals = { - 'room_lines': reservations, - 'wcustomer_notes': "%s\nADDONS:\n%s\nDISCOUNT:\n%s" % ( - book['customer_notes'], addons, discounts), - 'channel_type': 'web', - } - _logger.info("=== FOLIO CREATE") - _logger.info(reservations) - if folio_id: - folio_id.with_context({ - 'wubook_action': False}).write(vals) - else: - vals.update({ - 'partner_id': partner_id.id, - 'wseed': book['sessionSeed'] - }) - folio_id = hotel_folio_obj.with_context({ - 'wubook_action': False}).create(vals) - - # Update Reservation Spitted Parents - sorted_rlines = folio_id.room_lines.sorted(key='id') - for k_pid, v_pid in splitted_map.iteritems(): - preserv = sorted_rlines[k_pid-1] - for pid in v_pid: - creserv = sorted_rlines[pid-1] - creserv.parent_reservation = preserv.id - - processed_rids.append(rcode) - except Exception as e_msg: - self.create_wubook_issue( - 'reservation', - e_msg[0], - '', wid=rcode) - failed_reservations.append(crcode) - return (processed_rids, any(failed_reservations), - checkin_utc_dt, checkout_utc_dt) - - @api.model - def generate_wubook_channel_info(self, channels): - channel_info_obj = self.env['wubook.channel.info'] - count = 0 - for k_cid, v_cid in channels.iteritems(): - vals = { - 'name': v_cid['name'], - 'ical': v_cid['ical'] == 1, - } - channel_info = channel_info_obj.search([ - ('wid', '=', k_cid) - ], limit=1) - if channel_info: - channel_info.write(vals) - else: - vals.update({ - 'wid': k_cid - }) - channel_info_obj.create(vals) - count = count + 1 - return count - - # === ODOO -> WUBOOK - @api.model - def push_changes(self): - return self.push_availability() and self.push_priceplans() and \ - self.push_restrictions() - - @api.model - def push_availability(self): - vroom_avail_ids = self.env['hotel.virtual.room.availability'].search([ - ('wpushed', '=', False), - ('date', '>=', date_utils.now(hours=False).strftime( - DEFAULT_SERVER_DATE_FORMAT)) - ]) - - vrooms = vroom_avail_ids.mapped('virtual_room_id') - avails = [] - for vroom in vrooms: - vroom_avails = vroom_avail_ids.filtered( - lambda x: x.virtual_room_id.id == vroom.id) - days = [] - for vroom_avail in vroom_avails: - vroom_avail.with_context({ - 'wubook_action': False}).write({'wpushed': True}) - wavail = vroom_avail.avail - if wavail > vroom_avail.wmax_avail: - wavail = vroom_avail.wmax_avail - date_dt = date_utils.get_datetime( - vroom_avail.date, - dtformat=DEFAULT_SERVER_DATE_FORMAT) - days.append({ - 'date': date_dt.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - 'avail': wavail, - 'no_ota': vroom_avail.no_ota and 1 or 0, - # 'booked': vroom_avail.booked and 1 or 0, - }) - avails.append({'id': vroom.wrid, 'days': days}) - _logger.info("UPDATING AVAILABILITY IN WUBOOK...") - _logger.info(avails) - if any(avails): - self.update_availability(avails) - return True - - @api.model - def push_priceplans(self): - unpushed = self.env['product.pricelist.item'].search([ - ('wpushed', '=', False), - ('date_start', '>=', date_utils.now(hours=False).strftime( - DEFAULT_SERVER_DATE_FORMAT)) - ], order="date_start ASC") - if any(unpushed): - date_start = date_utils.get_datetime( - unpushed[0].date_start, - dtformat=DEFAULT_SERVER_DATE_FORMAT) - date_end = date_utils.get_datetime( - unpushed[-1].date_start, - dtformat=DEFAULT_SERVER_DATE_FORMAT) - days_diff = date_utils.date_diff(date_start, date_end, hours=False) + 1 - - prices = {} - pricelist_ids = self.env['product.pricelist'].search([ - ('wpid', '!=', False), - ('active', '=', True) - ]) - for pr in pricelist_ids: - prices.update({pr.wpid: {}}) - unpushed_pl = self.env['product.pricelist.item'].search( - [('wpushed', '=', False), ('pricelist_id', '=', pr.id)]) - product_tmpl_ids = unpushed_pl.mapped('product_tmpl_id') - for pt_id in product_tmpl_ids: - vroom = self.env['hotel.virtual.room'].search([ - ('product_id.product_tmpl_id', '=', pt_id.id) - ], limit=1) - if vroom: - prices[pr.wpid].update({vroom.wrid: []}) - for i in range(0, days_diff): - prod = vroom.product_id.with_context({ - 'quantity': 1, - 'pricelist': pr.id, - 'date': (date_start + timedelta(days=i)). - strftime(DEFAULT_SERVER_DATE_FORMAT), - }) - prices[pr.wpid][vroom.wrid].append(prod.price) - _logger.info("UPDATING PRICES IN WUBOOK...") - _logger.info(prices) - for k_pk, v_pk in prices.iteritems(): - if any(v_pk): - self.update_plan_prices(k_pk, date_start.strftime( - DEFAULT_WUBOOK_DATE_FORMAT), v_pk) - - unpushed.with_context({ - 'wubook_action': False}).write({'wpushed': True}) - return True - - @api.model - def push_restrictions(self): - vroom_rest_obj = self.env['hotel.virtual.room.restriction'] - rest_item_obj = self.env['hotel.virtual.room.restriction.item'] - unpushed = rest_item_obj.search([ - ('wpushed', '=', False), - ('date_start', '>=', date_utils.now(hours=False).strftime( - DEFAULT_SERVER_DATE_FORMAT)) - ], order="date_start ASC") - if any(unpushed): - date_start = date_utils.get_datetime( - unpushed[0].date_start, - dtformat=DEFAULT_SERVER_DATE_FORMAT) - date_end = date_utils.get_datetime( - unpushed[-1].date_start, - dtformat=DEFAULT_SERVER_DATE_FORMAT) - days_diff = date_utils.date_diff( - date_start, - date_end, - hours=False) + 1 - restrictions = {} - restriction_plan_ids = vroom_rest_obj.search([ - ('wpid', '!=', False), - ('active', '=', True) - ]) - for rp in restriction_plan_ids: - restrictions.update({rp.wpid: {}}) - unpushed_rp = rest_item_obj.search([ - ('wpushed', '=', False), - ('restriction_id', '=', rp.id) - ]) - virtual_room_ids = unpushed_rp.mapped('virtual_room_id') - for vroom in virtual_room_ids: - restrictions[rp.wpid].update({vroom.wrid: []}) - for i in range(0, days_diff): - ndate_dt = date_start + timedelta(days=i) - restr = vroom.get_restrictions( - ndate_dt.strftime(DEFAULT_SERVER_DATE_FORMAT)) - if restr: - restrictions[rp.wpid][vroom.wrid].append({ - 'min_stay': restr.min_stay or 0, - 'min_stay_arrival': restr.min_stay_arrival or 0, - 'max_stay': restr.max_stay or 0, - 'max_stay_arrival': restr.max_stay_arrival or 0, - 'closed': restr.closed and 1 or 0, - 'closed_arrival': restr.closed_arrival and 1 or 0, - 'closed_departure': restr.closed_departure and 1 or 0, - }) - else: - restrictions[rp.wpid][vroom.wrid].append({}) - _logger.info("UPDATING RESTRICTIONS IN WUBOOK...") - _logger.info(restrictions) - for k_res, v_res in restrictions.iteritems(): - if any(v_res): - self.update_rplan_values( - int(k_res), - date_start.strftime(DEFAULT_WUBOOK_DATE_FORMAT), - v_res) - unpushed.with_context({ - 'wubook_action': False}).write({'wpushed': True}) - return True