From 676e1b253f4c64a3ff0c466a477871f88415d309 Mon Sep 17 00:00:00 2001 From: Pablo Date: Wed, 17 Jul 2019 12:32:29 +0200 Subject: [PATCH 01/20] [ADD] Multi Hotel initial import --- hotel/__manifest__.py | 10 ++- hotel/data/hotel_data.xml | 16 +++++ hotel/models/__init__.py | 3 + hotel/models/hotel_property.py | 17 ++++++ hotel/models/inherited_ir_http.py | 20 ++++++ hotel/models/inherited_res_company.py | 2 + hotel/models/inherited_res_users.py | 17 ++++++ .../src/js/widgets/switch_hotel_menu.js | 61 +++++++++++++++++++ hotel/static/src/xml/hotel_base_templates.xml | 12 ++++ hotel/views/hotel_property_views.xml | 50 +++++++++++++++ hotel/views/inherited_res_company_views.xml | 20 ++++++ hotel/views/inherited_res_users_views.xml | 17 ++++++ hotel/views/inherited_webclient_templates.xml | 10 +++ 13 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 hotel/data/hotel_data.xml create mode 100644 hotel/models/hotel_property.py create mode 100644 hotel/models/inherited_ir_http.py create mode 100644 hotel/models/inherited_res_users.py create mode 100644 hotel/static/src/js/widgets/switch_hotel_menu.js create mode 100644 hotel/static/src/xml/hotel_base_templates.xml create mode 100644 hotel/views/hotel_property_views.xml create mode 100644 hotel/views/inherited_res_company_views.xml create mode 100644 hotel/views/inherited_res_users_views.xml create mode 100644 hotel/views/inherited_webclient_templates.xml diff --git a/hotel/__manifest__.py b/hotel/__manifest__.py index 634c2b78f..a523ec183 100644 --- a/hotel/__manifest__.py +++ b/hotel/__manifest__.py @@ -9,7 +9,7 @@ Darío Lodeiros,\ Jose Luis Algara,\ Alexandre Díaz,\ - Q. Barriuso,', + Pablo Quesada,', 'category': 'Generic Modules/Hotel Management', 'website': 'https://github.com/hootel/hootel', 'depends': [ @@ -22,6 +22,7 @@ 'license': "AGPL-3", 'demo': ['data/hotel_demo.xml'], 'data': [ + 'data/hotel_data.xml', 'security/hotel_security.xml', 'security/ir.model.access.csv', 'wizard/massive_changes.xml', @@ -35,6 +36,9 @@ 'wizard/massive_price_reservation_days.xml', 'wizard/folio_make_invoice_advance_views.xml', 'data/hotel_sequence.xml', + 'views/inherited_res_company_views.xml', + 'views/inherited_res_users_views.xml', + 'views/hotel_property_views.xml', 'views/hotel_floor_views.xml', 'views/hotel_folio_views.xml', 'views/inherited_res_partner_views.xml', @@ -57,6 +61,7 @@ 'views/hotel_checkin_partner_views.xml', 'views/hotel_board_service_room_type_views.xml', 'views/hotel_cancelation_rule_views.xml', + 'views/inherited_webclient_templates.xml', 'data/cron_jobs.xml', 'data/records.xml', 'data/email_template_cancel.xml', @@ -66,5 +71,8 @@ 'report/hotel_folio_templates.xml', 'report/hotel_folio.xml' ], + 'qweb': [ + 'static/src/xml/*.xml', + ], 'installable': True } diff --git a/hotel/data/hotel_data.xml b/hotel/data/hotel_data.xml new file mode 100644 index 000000000..a6d0c1df9 --- /dev/null +++ b/hotel/data/hotel_data.xml @@ -0,0 +1,16 @@ + + + + + + + My Hotel + + + + + + + + + \ No newline at end of file diff --git a/hotel/models/__init__.py b/hotel/models/__init__.py index b56e8af46..d0664b9a5 100644 --- a/hotel/models/__init__.py +++ b/hotel/models/__init__.py @@ -2,8 +2,11 @@ # Copyright 2018 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from . import inherited_ir_http from . import inherited_payment_return from . import hotel_board_service_room_type +from . import hotel_property +from . import inherited_res_users from . import hotel_floor from . import hotel_folio from . import hotel_reservation diff --git a/hotel/models/hotel_property.py b/hotel/models/hotel_property.py new file mode 100644 index 000000000..0128d50e4 --- /dev/null +++ b/hotel/models/hotel_property.py @@ -0,0 +1,17 @@ +# Copyright 2019 Pablo Quesada +# Copyright 2019 Dario Lodeiros +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models, api, fields + + +class HotelProperty(models.Model): + _name = 'hotel.property' + _description = 'Hotel' + _inherits = {'res.partner': 'partner_id'} + + partner_id = fields.Many2one('res.partner', 'Hotel Property', + required=True, delegate=True, ondelete='cascade') + company_id = fields.Many2one('res.company', help='The company that owns or operates this hotel.') + user_ids = fields.Many2many('res.users', 'hotel_property_users_rel', 'hotel_id', 'user_id', + string='Accepted Users') diff --git a/hotel/models/inherited_ir_http.py b/hotel/models/inherited_ir_http.py new file mode 100644 index 000000000..f15ca02a4 --- /dev/null +++ b/hotel/models/inherited_ir_http.py @@ -0,0 +1,20 @@ +# Copyright 2019 Pablo Quesada +# Copyright 2019 Dario Lodeiros +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import models +from odoo.http import request + + +class IrHttp(models.AbstractModel): + _inherit = 'ir.http' + + def session_info(self): + res = super().session_info() + user = request.env.user + display_switch_hotel_menu = len(user.hotel_ids) > 1 + res['hotel_id'] = request.env.user.hotel_id.id if request.session.uid else None + res['user_hotels'] = {'current_hotel': (user.hotel_id.id, user.hotel_id.name), + 'allowed_hotels': [(hotel.id, hotel.name) for hotel in + user.hotel_ids]} if display_switch_hotel_menu else False + return res diff --git a/hotel/models/inherited_res_company.py b/hotel/models/inherited_res_company.py index 7173b6635..0eb942f7a 100644 --- a/hotel/models/inherited_res_company.py +++ b/hotel/models/inherited_res_company.py @@ -7,6 +7,8 @@ from odoo import models, fields class ResCompany(models.Model): _inherit = 'res.company' + hotel_ids = fields.One2many('hotel.property', 'company_id', 'Hotels') + additional_hours = fields.Integer('Additional Hours', help="Provide the min hours value for \ check in, checkout days, whatever \ diff --git a/hotel/models/inherited_res_users.py b/hotel/models/inherited_res_users.py new file mode 100644 index 000000000..0adb77138 --- /dev/null +++ b/hotel/models/inherited_res_users.py @@ -0,0 +1,17 @@ +# Copyright 2019 Pablo Quesada +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). +from odoo import models, api, fields + + +class ResUsers(models.Model): + _inherit = 'res.users' + + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + + hotel_id = fields.Many2one('hotel.property', string='Hotel', default=_get_default_hotel, + help='The hotel this user is currently working for.', + context={'user_preference': True}) + hotel_ids = fields.Many2many('hotel.property', 'hotel_property_users_rel', 'user_id', 'hotel_id', + string='Hotels', default=_get_default_hotel) diff --git a/hotel/static/src/js/widgets/switch_hotel_menu.js b/hotel/static/src/js/widgets/switch_hotel_menu.js new file mode 100644 index 000000000..fdc5562ef --- /dev/null +++ b/hotel/static/src/js/widgets/switch_hotel_menu.js @@ -0,0 +1,61 @@ +odoo.define('hotel.SwitchHotelMenu', function(require) { +"use strict"; + +var config = require('web.config'); +var core = require('web.core'); +var session = require('web.session'); +var SystrayMenu = require('web.SystrayMenu'); +var Widget = require('web.Widget'); + +var _t = core._t; + +var SwitchHotelMenu = Widget.extend({ + template: 'hotel.SwitchHotelMenu', + willStart: function() { + this.isMobile = config.device.isMobile; + if (!session.user_hotels) { + return $.Deferred().reject(); + } + return this._super(); + }, + start: function() { + var self = this; + this.$el.on('click', '.dropdown-menu li a[data-menu]', _.debounce(function(ev) { + ev.preventDefault(); + var hotel_id = $(ev.currentTarget).data('hotel-id'); + self._rpc({ + model: 'res.users', + method: 'write', + args: [[session.uid], {'hotel_id': hotel_id}], + }) + .then(function() { + location.reload(); + }); + }, 1500, true)); + + var hotels_list = ''; + if (this.isMobile) { + hotels_list = '
  • ' + _t('Tap on the list to change hotel') + '
  • '; + } + else { + self.$('.oe_topbar_name').text(session.user_hotels.current_hotel[1]); + } + _.each(session.user_hotels.allowed_hotels, function(hotel) { + var a = ''; + if (hotel[0] === session.user_hotels.current_hotel[0]) { + a = ''; + } else { + a = ''; + } + hotels_list += '
  • ' + a + hotel[1] + '
  • '; + }); + self.$('.dropdown-menu').html(hotels_list); + return this._super(); + }, +}); + +SystrayMenu.Items.push(SwitchHotelMenu); + +return SwitchHotelMenu; + +}); diff --git a/hotel/static/src/xml/hotel_base_templates.xml b/hotel/static/src/xml/hotel_base_templates.xml new file mode 100644 index 000000000..0a9895114 --- /dev/null +++ b/hotel/static/src/xml/hotel_base_templates.xml @@ -0,0 +1,12 @@ + diff --git a/hotel/views/hotel_property_views.xml b/hotel/views/hotel_property_views.xml new file mode 100644 index 000000000..de6761bf4 --- /dev/null +++ b/hotel/views/hotel_property_views.xml @@ -0,0 +1,50 @@ + + + + + + + hotel_property_views_form + hotel.property + +
    + + +
    +
    +
    + + + hotel_property_views_tree + hotel.property + + + + + + + + + + + + Hotel Property + hotel.property + form + tree,form + + +
    diff --git a/hotel/views/inherited_res_company_views.xml b/hotel/views/inherited_res_company_views.xml new file mode 100644 index 000000000..aea69d8b9 --- /dev/null +++ b/hotel/views/inherited_res_company_views.xml @@ -0,0 +1,20 @@ + + + + + + view.company.form + res.company + + + + + + + + + + + + + diff --git a/hotel/views/inherited_res_users_views.xml b/hotel/views/inherited_res_users_views.xml new file mode 100644 index 000000000..45b3cbcc9 --- /dev/null +++ b/hotel/views/inherited_res_users_views.xml @@ -0,0 +1,17 @@ + + + + + res.users + + + + + + + + + + + + diff --git a/hotel/views/inherited_webclient_templates.xml b/hotel/views/inherited_webclient_templates.xml new file mode 100644 index 000000000..10f1dea10 --- /dev/null +++ b/hotel/views/inherited_webclient_templates.xml @@ -0,0 +1,10 @@ + + + + + + From 8f9b63d56226d46cfbecf7a335a0de41bdf9b06d Mon Sep 17 00:00:00 2001 From: Pablo Date: Fri, 19 Jul 2019 11:47:51 +0200 Subject: [PATCH 02/20] [WIP] Manage multihotel and multicompany --- hotel/models/hotel_property.py | 3 +++ hotel/models/hotel_room.py | 8 ++++++++ hotel/models/hotel_room_type.py | 7 +++++++ hotel/models/inherited_ir_http.py | 12 +++++++++++- hotel/views/hotel_room_type_views.xml | 1 + hotel/views/hotel_room_views.xml | 1 + 6 files changed, 31 insertions(+), 1 deletion(-) diff --git a/hotel/models/hotel_property.py b/hotel/models/hotel_property.py index 0128d50e4..5172c259a 100644 --- a/hotel/models/hotel_property.py +++ b/hotel/models/hotel_property.py @@ -15,3 +15,6 @@ class HotelProperty(models.Model): company_id = fields.Many2one('res.company', help='The company that owns or operates this hotel.') user_ids = fields.Many2many('res.users', 'hotel_property_users_rel', 'hotel_id', 'user_id', string='Accepted Users') + + room_type_ids = fields.One2many('hotel.room.type', 'hotel_id', 'Room Types') + room_ids = fields.One2many('hotel.room', 'hotel_id', 'Room') diff --git a/hotel/models/hotel_room.py b/hotel/models/hotel_room.py index 114190469..4191c9b65 100644 --- a/hotel/models/hotel_room.py +++ b/hotel/models/hotel_room.py @@ -5,6 +5,7 @@ from odoo import models, fields, api, _ from odoo.exceptions import ValidationError + class HotelRoom(models.Model): """ The rooms for lodging can be for sleeping, usually called rooms, and also for speeches (conference rooms), parking, relax with cafe con leche, spa... @@ -13,6 +14,10 @@ class HotelRoom(models.Model): _description = 'Hotel Room' _order = "sequence, room_type_id, name" + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + name = fields.Char('Room Name', required=True) active = fields.Boolean('Active', default=True) sequence = fields.Integer('Sequence', default=0) @@ -21,6 +26,9 @@ class HotelRoom(models.Model): ondelete='restrict') floor_id = fields.Many2one('hotel.floor', 'Ubication', help='At which floor the room is located.') + hotel_id = fields.Many2one('hotel.property', 'Hotel', required=True, ondelete='restrict', + default=_get_default_hotel,) + max_adult = fields.Integer('Max Adult') max_child = fields.Integer('Max Child') capacity = fields.Integer('Capacity') diff --git a/hotel/models/hotel_room_type.py b/hotel/models/hotel_room_type.py index cc85c269f..09ca4ba26 100644 --- a/hotel/models/hotel_room_type.py +++ b/hotel/models/hotel_room_type.py @@ -4,6 +4,7 @@ from odoo import models, fields, api, _ from odoo.exceptions import ValidationError + class HotelRoomType(models.Model): """ Before creating a 'room type', you need to consider the following: With the term 'room type' is meant a sales type of residential accommodation: for @@ -13,6 +14,10 @@ class HotelRoomType(models.Model): _description = "Room Type" _inherits = {'product.product': 'product_id'} + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + # Relationship between models product_id = fields.Many2one('product.product', 'Product Room Type', required=True, delegate=True, @@ -26,6 +31,8 @@ class HotelRoomType(models.Model): 'room_type_ids', 'amenity_ids', string='Room Type Amenities', help='List of Amenities.') + hotel_id = fields.Many2one('hotel.property', 'Hotel', required=True, ondelete='restrict', + default=_get_default_hotel,) # TODO Hierarchical relationship for parent-child tree ? # parent_id = fields.Many2one ... diff --git a/hotel/models/inherited_ir_http.py b/hotel/models/inherited_ir_http.py index f15ca02a4..6a7725db8 100644 --- a/hotel/models/inherited_ir_http.py +++ b/hotel/models/inherited_ir_http.py @@ -2,8 +2,9 @@ # Copyright 2019 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models +from odoo import models, _ from odoo.http import request +from odoo.exceptions import MissingError class IrHttp(models.AbstractModel): @@ -13,8 +14,17 @@ class IrHttp(models.AbstractModel): res = super().session_info() user = request.env.user display_switch_hotel_menu = len(user.hotel_ids) > 1 + # TODO: limit hotels to the current company? or switch company automatically res['hotel_id'] = request.env.user.hotel_id.id if request.session.uid else None res['user_hotels'] = {'current_hotel': (user.hotel_id.id, user.hotel_id.name), 'allowed_hotels': [(hotel.id, hotel.name) for hotel in user.hotel_ids]} if display_switch_hotel_menu else False + if user.hotel_id.company_id in user.company_ids: + user.company_id = user.hotel_id.company_id + res['company_id'] = user.hotel_id.company_id.id + else: + raise MissingError( + _("Wrong hotel and company access settings for this user. " + "Please review hotel and company for user %s") % user.name) + return res diff --git a/hotel/views/hotel_room_type_views.xml b/hotel/views/hotel_room_type_views.xml index 15aa43600..d98360627 100644 --- a/hotel/views/hotel_room_type_views.xml +++ b/hotel/views/hotel_room_type_views.xml @@ -66,6 +66,7 @@ + diff --git a/hotel/views/hotel_room_views.xml b/hotel/views/hotel_room_views.xml index 9f48ceab0..57571bae4 100644 --- a/hotel/views/hotel_room_views.xml +++ b/hotel/views/hotel_room_views.xml @@ -126,6 +126,7 @@ + From 42dde0b18c4305b0e628748dfa9d64b7e0f7b128 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Wed, 31 Jul 2019 14:17:58 +0200 Subject: [PATCH 03/20] [WIP] Basic multihotel modeling --- hotel/models/hotel_amenity.py | 3 ++ hotel/models/hotel_amenity_type.py | 9 ++-- hotel/models/hotel_board_service.py | 1 + hotel/models/hotel_board_service_line.py | 2 + hotel/models/hotel_board_service_room_type.py | 2 + .../hotel_board_service_room_type_line.py | 2 + hotel/models/hotel_cancelation_rule.py | 4 ++ hotel/models/hotel_checkin_partner.py | 6 +++ hotel/models/hotel_floor.py | 1 + hotel/models/hotel_folio.py | 6 +++ hotel/models/hotel_reservation.py | 2 + hotel/models/hotel_reservation_line.py | 2 + hotel/models/hotel_room.py | 8 +--- hotel/models/hotel_room_closure_reason.py | 2 + hotel/models/hotel_room_type_class.py | 2 + hotel/models/hotel_room_type_restriction.py | 6 +++ .../hotel_room_type_restriction_item.py | 2 + hotel/models/hotel_service.py | 2 + hotel/models/hotel_service_line.py | 2 + hotel/models/hotel_shared_room.py | 2 + hotel/models/inherited_account_invoice.py | 1 + hotel/models/inherited_payment_return.py | 2 + hotel/models/inherited_product_pricelist.py | 2 + hotel/models/inherited_product_template.py | 2 + hotel/views/hotel_board_service_views.xml | 2 + hotel/views/hotel_cancelation_rule_views.xml | 2 + hotel/views/hotel_checkin_partner_views.xml | 1 + hotel/views/hotel_floor_views.xml | 2 + hotel/views/hotel_folio_views.xml | 2 +- hotel/views/hotel_reservation_views.xml | 3 ++ .../views/hotel_room_amenities_type_views.xml | 2 + hotel/views/hotel_room_amenities_views.xml | 4 +- .../views/hotel_room_closure_reason_views.xml | 2 + hotel/views/hotel_room_type_class_views.xml | 2 + .../hotel_room_type_restriction_views.xml | 15 +++--- hotel/views/hotel_room_type_views.xml | 1 + hotel/views/hotel_room_views.xml | 1 + hotel/views/hotel_service_line_views.xml | 2 + hotel/views/hotel_service_type_views.xml | 48 ------------------- hotel/views/hotel_service_views.xml | 4 ++ .../views/inherited_account_invoice_views.xml | 1 + .../inherited_product_pricelist_views.xml | 2 + .../inherited_product_template_views.xml | 2 + 43 files changed, 106 insertions(+), 65 deletions(-) delete mode 100644 hotel/views/hotel_service_type_views.xml diff --git a/hotel/models/hotel_amenity.py b/hotel/models/hotel_amenity.py index 045acecad..da5a11c0b 100644 --- a/hotel/models/hotel_amenity.py +++ b/hotel/models/hotel_amenity.py @@ -12,3 +12,6 @@ class HotelRoomAmenitie(models.Model): default_code = fields.Char('Internal Reference') room_amenity_type_id = fields.Many2one('hotel.amenity.type', 'Amenity Catagory') + hotel_ids = fields.Many2many('hotel.property', 'Hotels', required=False, ondelete='restrict') + + #TODO: Constrain coherence hotel_ids with amenity types hotel_ids diff --git a/hotel/models/hotel_amenity_type.py b/hotel/models/hotel_amenity_type.py index 89acae297..8ad160eeb 100644 --- a/hotel/models/hotel_amenity_type.py +++ b/hotel/models/hotel_amenity_type.py @@ -1,7 +1,7 @@ # Copyright 2017 Alexandre Díaz # Copyright 2017 Dario Lodeiros # License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). -from odoo import models, fields +from odoo import models, fields, api class HotelRoomAmenitieType(models.Model): @@ -11,5 +11,8 @@ class HotelRoomAmenitieType(models.Model): name = fields.Char('Amenity Name', translate=True, required=True) active = fields.Boolean('Active', default=True) room_amenity_ids = fields.One2many('hotel.amenity', - 'room_amenity_type_id', - 'Amenities in this category') + 'room_amenity_type_id', + 'Amenities in this category') + hotel_ids = fields.Many2many('hotel.property', 'Hotels', required=False, ondelete='restrict') + + #TODO: Constrain coherence hotel_ids with amenities hotel_ids diff --git a/hotel/models/hotel_board_service.py b/hotel/models/hotel_board_service.py index da398e205..32f8313fe 100644 --- a/hotel/models/hotel_board_service.py +++ b/hotel/models/hotel_board_service.py @@ -20,6 +20,7 @@ class HotelBoardService(models.Model): digits=dp.get_precision('Product Price'), compute='_compute_board_amount', store=True) + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, ondelete='restrict') @api.depends('board_service_line_ids.amount') def _compute_board_amount(self): diff --git a/hotel/models/hotel_board_service_line.py b/hotel/models/hotel_board_service_line.py index 0199bd5aa..8b9f4e8b9 100644 --- a/hotel/models/hotel_board_service_line.py +++ b/hotel/models/hotel_board_service_line.py @@ -24,6 +24,8 @@ class HotelBoardServiceLine(models.Model): 'Amount', digits=dp.get_precision('Product Price'), default=_get_default_price) + hotel_ids = fields.Many2many('hotel.property', + related='hotel_board_service_id.hotel_ids') @api.onchange('product_id') def onchange_product_id(self): diff --git a/hotel/models/hotel_board_service_room_type.py b/hotel/models/hotel_board_service_room_type.py index 884571665..69e74e9dd 100644 --- a/hotel/models/hotel_board_service_room_type.py +++ b/hotel/models/hotel_board_service_room_type.py @@ -37,6 +37,8 @@ class HotelBoardServiceRoomType(models.Model): compute='_compute_board_amount', store=True) board_service_line_ids = fields.One2many('hotel.board.service.room.type.line', 'hotel_board_service_room_type_id') + hotel_id = fields.Many2one('hotel.property', + related='hotel_room_type_id.hotel_id') @api.model_cr def init(self): diff --git a/hotel/models/hotel_board_service_room_type_line.py b/hotel/models/hotel_board_service_room_type_line.py index 8fcbb6afd..ba7757094 100644 --- a/hotel/models/hotel_board_service_room_type_line.py +++ b/hotel/models/hotel_board_service_room_type_line.py @@ -11,6 +11,8 @@ class HotelBoardServiceRoomTypeLine(models.Model): #TODO def default_amount "amount of service" + + hotel_board_service_room_type_id = fields.Many2one( 'hotel.board.service.room.type', 'Board Service Room', ondelete='cascade', required=True) product_id = fields.Many2one( diff --git a/hotel/models/hotel_cancelation_rule.py b/hotel/models/hotel_cancelation_rule.py index 0415d3b56..4280b766e 100644 --- a/hotel/models/hotel_cancelation_rule.py +++ b/hotel/models/hotel_cancelation_rule.py @@ -28,3 +28,7 @@ class HotelCancelationRule(models.Model): ('all', 'All Days'), ('days', 'Specify days')], 'No Show apply on', default='all') days_noshow = fields.Integer('NoShow first days', default="2") + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, + ondelete='restrict') + + #TODO: Constrain coherence hotel_ids pricelist and cancelation_rules diff --git a/hotel/models/hotel_checkin_partner.py b/hotel/models/hotel_checkin_partner.py index 18797da05..6456bc514 100644 --- a/hotel/models/hotel_checkin_partner.py +++ b/hotel/models/hotel_checkin_partner.py @@ -68,6 +68,10 @@ class HotelCheckinPartner(models.Model): return reservation.checkout return False + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + partner_id = fields.Many2one('res.partner', default=_default_partner_id, required=True) email = fields.Char('E-mail', related='partner_id.email') @@ -91,6 +95,8 @@ class HotelCheckinPartner(models.Model): 'State', readonly=True, default=lambda *a: 'draft', track_visibility='onchange') + hotel_id = fields.Many2one('hotel.property', default=_get_default_hotel, + required=True) @api.model def create(self, vals): diff --git a/hotel/models/hotel_floor.py b/hotel/models/hotel_floor.py index f65f2dbe6..0dacdec10 100644 --- a/hotel/models/hotel_floor.py +++ b/hotel/models/hotel_floor.py @@ -9,3 +9,4 @@ class HotelFloor(models.Model): name = fields.Char('Ubication Name', translate=True, size=64, required=True, index=True) sequence = fields.Integer('Sequence') + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, ondelete='restrict') diff --git a/hotel/models/hotel_folio.py b/hotel/models/hotel_folio.py index bd7a68a2c..32123c823 100644 --- a/hotel/models/hotel_folio.py +++ b/hotel/models/hotel_folio.py @@ -94,10 +94,16 @@ class HotelFolio(models.Model): def _get_default_team(self): return self.env['crm.team']._get_default_team_id() + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + #Main Fields-------------------------------------------------------- name = fields.Char('Folio Number', readonly=True, index=True, default=lambda self: _('New')) client_order_ref = fields.Char(string='Customer Reference', copy=False) + hotel_id = fields.Many2one('hotel.property', default=_get_default_hotel, + required=True) partner_id = fields.Many2one('res.partner', track_visibility='onchange', ondelete='restrict',) diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index efe4c7044..7431f444d 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -240,6 +240,8 @@ class HotelReservation(models.Model): partner_parent_id = fields.Many2one(related="partner_id.parent_id") closure_reason_id = fields.Many2one(related='folio_id.closure_reason_id') company_id = fields.Many2one(related='folio_id.company_id', string='Company', store=True, readonly=True) + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='folio_id.hotel_id') reservation_line_ids = fields.One2many('hotel.reservation.line', 'reservation_id', required=True) diff --git a/hotel/models/hotel_reservation_line.py b/hotel/models/hotel_reservation_line.py index a1b80c29b..ac1625482 100644 --- a/hotel/models/hotel_reservation_line.py +++ b/hotel/models/hotel_reservation_line.py @@ -37,6 +37,8 @@ class HotelReservationLine(models.Model): 'reservation_line_invoice_rel', 'reservation_line_id', 'invoice_line_id', string='Invoice Lines', readonly=True, copy=False) + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='reservation_id.hotel_id') @api.constrains('date') def constrains_duplicated_date(self): diff --git a/hotel/models/hotel_room.py b/hotel/models/hotel_room.py index 4191c9b65..01dad3d52 100644 --- a/hotel/models/hotel_room.py +++ b/hotel/models/hotel_room.py @@ -14,10 +14,6 @@ class HotelRoom(models.Model): _description = 'Hotel Room' _order = "sequence, room_type_id, name" - @api.model - def _get_default_hotel(self): - return self.env.user.hotel_id - name = fields.Char('Room Name', required=True) active = fields.Boolean('Active', default=True) sequence = fields.Integer('Sequence', default=0) @@ -26,8 +22,8 @@ class HotelRoom(models.Model): ondelete='restrict') floor_id = fields.Many2one('hotel.floor', 'Ubication', help='At which floor the room is located.') - hotel_id = fields.Many2one('hotel.property', 'Hotel', required=True, ondelete='restrict', - default=_get_default_hotel,) + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='room_type_id.hotel_id') max_adult = fields.Integer('Max Adult') max_child = fields.Integer('Max Child') diff --git a/hotel/models/hotel_room_closure_reason.py b/hotel/models/hotel_room_closure_reason.py index b80b9ad46..c497c2149 100644 --- a/hotel/models/hotel_room_closure_reason.py +++ b/hotel/models/hotel_room_closure_reason.py @@ -8,3 +8,5 @@ class RoomClosureReason(models.Model): name = fields.Char('Name', translate=True, required=True) description = fields.Text('Description', translate=True) + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, + ondelete='restrict') diff --git a/hotel/models/hotel_room_type_class.py b/hotel/models/hotel_room_type_class.py index a5b1a6f53..09b1550bf 100644 --- a/hotel/models/hotel_room_type_class.py +++ b/hotel/models/hotel_room_type_class.py @@ -20,6 +20,8 @@ class HotelRoomTypeClass(models.Model): category without removing it.") sequence = fields.Integer('Sequence', default=0) code_class = fields.Char('Code') + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, + ondelete='restrict') _sql_constraints = [('code_class_unique', 'unique(code_class)', 'code must be unique!')] diff --git a/hotel/models/hotel_room_type_restriction.py b/hotel/models/hotel_room_type_restriction.py index cdeb3985f..f07fabd78 100644 --- a/hotel/models/hotel_room_type_restriction.py +++ b/hotel/models/hotel_room_type_restriction.py @@ -6,6 +6,10 @@ from odoo import models, fields, api class HotelRoomTypeRestriction(models.Model): _name = 'hotel.room.type.restriction' + @api.model + def _get_default_hotel(self): + return self.env.user.hotel_id + name = fields.Char('Restriction Plan Name', required=True) item_ids = fields.One2many('hotel.room.type.restriction.item', 'restriction_id', string='Restriction Items', @@ -14,6 +18,8 @@ class HotelRoomTypeRestriction(models.Model): help='If unchecked, it will allow you to hide the \ restriction plan without removing it.', default=True) + hotel_id = fields.Many2one('hotel.property', default=_get_default_hotel, + required=True, ondelete='cascade') @api.multi @api.depends('name') diff --git a/hotel/models/hotel_room_type_restriction_item.py b/hotel/models/hotel_room_type_restriction_item.py index 8414b9947..7783d0cfd 100644 --- a/hotel/models/hotel_room_type_restriction_item.py +++ b/hotel/models/hotel_room_type_restriction_item.py @@ -21,6 +21,8 @@ class HotelRoomTypeRestrictionItem(models.Model): closed = fields.Boolean('Closed') closed_departure = fields.Boolean('Closed Departure') closed_arrival = fields.Boolean('Closed Arrival') + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='restriction_id.hotel_id') _sql_constraints = [('room_type_registry_unique', 'unique(restriction_id, room_type_id, date)', diff --git a/hotel/models/hotel_service.py b/hotel/models/hotel_service.py index 23db11ef5..0ec65aa26 100644 --- a/hotel/models/hotel_service.py +++ b/hotel/models/hotel_service.py @@ -132,6 +132,8 @@ class HotelService(models.Model): # Non-stored related field to allow portal user to see the image of the product he has ordered product_image = fields.Binary('Product Image', related="product_id.image", store=False, related_sudo=True) company_id = fields.Many2one(related='folio_id.company_id', string='Company', store=True, readonly=True) + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='folio_id.hotel_id') invoice_status = fields.Selection([ ('invoiced', 'Fully Invoiced'), ('to invoice', 'To Invoice'), diff --git a/hotel/models/hotel_service_line.py b/hotel/models/hotel_service_line.py index e909b72b2..ee4daf578 100644 --- a/hotel/models/hotel_service_line.py +++ b/hotel/models/hotel_service_line.py @@ -35,6 +35,8 @@ class HotelServiceLine(models.Model): string='Taxes', related="service_id.tax_ids", readonly="True") + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='service_id.hotel_id') def _cancel_discount(self): for record in self: diff --git a/hotel/models/hotel_shared_room.py b/hotel/models/hotel_shared_room.py index 976484aff..ee58a4ee6 100644 --- a/hotel/models/hotel_shared_room.py +++ b/hotel/models/hotel_shared_room.py @@ -18,6 +18,8 @@ class HotelSharedRoom(models.Model): required=True, ondelete='restrict', domain=[('shared_room', '=', True)] ) + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='room_type_id.hotel_id') floor_id = fields.Many2one('hotel.floor', 'Ubication', help='At which floor the room is located.', ondelete='restrict',) diff --git a/hotel/models/inherited_account_invoice.py b/hotel/models/inherited_account_invoice.py index a8d99aba3..a002505b4 100644 --- a/hotel/models/inherited_account_invoice.py +++ b/hotel/models/inherited_account_invoice.py @@ -38,6 +38,7 @@ class AccountInvoice(models.Model): from_folio = fields.Boolean(compute='_computed_folio_origin') folio_ids = fields.Many2many( comodel_name='hotel.folio', compute='_computed_folio_origin') + hotel_id = fields.Many2one('hotel.property') outstanding_folios_debits_widget = fields.Text(compute='_get_outstanding_folios_JSON') has_folios_outstanding = fields.Boolean(compute='_get_outstanding_folios_JSON') diff --git a/hotel/models/inherited_payment_return.py b/hotel/models/inherited_payment_return.py index b137d5034..d8382e317 100644 --- a/hotel/models/inherited_payment_return.py +++ b/hotel/models/inherited_payment_return.py @@ -7,6 +7,8 @@ class PaymentReturn(models.Model): _inherit = 'payment.return' folio_id = fields.Many2one('hotel.folio', string='Folio') + hotel_id = fields.Many2one('hotel.property', store=True, readonly=True, + related='folio_id.hotel_id') @api.multi def action_confirm(self): diff --git a/hotel/models/inherited_product_pricelist.py b/hotel/models/inherited_product_pricelist.py index 2296f9855..ac2e7d6a6 100644 --- a/hotel/models/inherited_product_pricelist.py +++ b/hotel/models/inherited_product_pricelist.py @@ -14,6 +14,8 @@ class ProductPricelist(models.Model): cancelation_rule_id = fields.Many2one( 'hotel.cancelation.rule', string="Cancelation Policy") + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, + ondelete='restrict') @api.multi @api.depends('name') diff --git a/hotel/models/inherited_product_template.py b/hotel/models/inherited_product_template.py index a47c546e6..bcd0e7079 100644 --- a/hotel/models/inherited_product_template.py +++ b/hotel/models/inherited_product_template.py @@ -16,3 +16,5 @@ class ProductTemplate(models.Model): is_extra_bed = fields.Boolean('Is extra bed', default=False) show_in_calendar = fields.Boolean('Show in Calendar', default=False, help='Specifies if the product is shown in the calendar information.') + hotel_ids = fields.Many2many('hotel.property', string='Hotels', required=False, + ondelete='restrict') diff --git a/hotel/views/hotel_board_service_views.xml b/hotel/views/hotel_board_service_views.xml index c8dd7dba2..99083ab0f 100644 --- a/hotel/views/hotel_board_service_views.xml +++ b/hotel/views/hotel_board_service_views.xml @@ -10,6 +10,8 @@
    + diff --git a/hotel/views/hotel_cancelation_rule_views.xml b/hotel/views/hotel_cancelation_rule_views.xml index d765373bc..8c19b69b1 100644 --- a/hotel/views/hotel_cancelation_rule_views.xml +++ b/hotel/views/hotel_cancelation_rule_views.xml @@ -11,6 +11,8 @@

    +