From 586c619ba0692309b7e7a79be6e9c36a42b397ba Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Tue, 20 Nov 2018 16:21:28 +0100 Subject: [PATCH 1/5] [ADD] Board service in reservation --- hotel/models/hotel_reservation.py | 1 + hotel/views/hotel_reservation_views.xml | 1 + 2 files changed, 2 insertions(+) diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index 1c1d1218b..d4769203b 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -133,6 +133,7 @@ class HotelReservation(models.Model): track_visibility='onchange') reservation_type = fields.Selection(related='folio_id.reservation_type', default=lambda *a: 'normal') + board_service_id = fields.Many2one('hotel.board.service', string='Board Service') cancelled_reason = fields.Selection([ ('late', 'Late'), ('intime', 'In time'), diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index 4302f78ab..cb67aa58f 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -189,6 +189,7 @@ + From 81d3bb069d99bf6e6fcd3cb09473d97e66f3b4ae Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Mon, 26 Nov 2018 11:22:46 +0100 Subject: [PATCH 2/5] [ADD] Board service in reservation --- hotel/models/hotel_board_service.py | 4 +-- hotel/models/hotel_reservation.py | 23 ++++++++++++++-- hotel/models/hotel_service.py | 35 ++++++++++++++++++++----- hotel/views/hotel_reservation_views.xml | 8 +++++- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/hotel/models/hotel_board_service.py b/hotel/models/hotel_board_service.py index c4774e4d7..4fcff0aa4 100644 --- a/hotel/models/hotel_board_service.py +++ b/hotel/models/hotel_board_service.py @@ -8,8 +8,8 @@ class HotelBoardService(models.Model): _description = "Board Services" name = fields.Char('Board Name', size=64, required=True, index=True) - service_ids = fields.Many2many(comodel_name='product.template', - relation='hotel_board_services_room', + service_ids = fields.Many2many(comodel_name='product.product', + relation='hotel_board_services_reservation', column1='board_id', column2='service_id') sequence = fields.Integer('Sequence') diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index d4769203b..b950af86e 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -408,7 +408,7 @@ class HotelReservation(models.Model): def open_folio(self): action = self.env.ref('hotel.open_hotel_folio1_form_tree_all').read()[0] if self.folio_id: - action['views'] = [(self.env.ref('hotel.view_hotel_folio1_form').id, 'form')] + action['views'] = [(self.env.ref('hotel.hotel_folio_view_form').id, 'form')] action['res_id'] = self.folio_id.id else: action = {'type': 'ir.actions.act_window_close'} @@ -417,7 +417,7 @@ class HotelReservation(models.Model): @api.multi def open_reservation_form(self): action = self.env.ref('hotel.open_hotel_reservation_form_tree_all').read()[0] - action['views'] = [(self.env.ref('hotel.view_hotel_reservation_form').id, 'form')] + action['views'] = [(self.env.ref('hotel.hotel_reservation_view_form').id, 'form')] action['res_id'] = self.id return action @@ -564,6 +564,25 @@ class HotelReservation(models.Model): ] return {'domain': {'room_id': domain_rooms}} + @api.onchange('board_service_id') + def onchange_board_service(self): + if self.board_service_id: + self.service_line_ids.filtered(lambda r: r.is_board_service == True).unlink() + board_services = [] + for product in self.board_service_id.service_ids: + board_services.append((0, False, { + 'product_id': product.id, + 'is_board_service': True, + })) + # NEED REVIEW: Why I need add manually the old IDs if board service is (0,0,(-)) ¿?¿?¿ + self.update({'service_line_ids': [(6, 0, self.service_line_ids.ids)] + board_services}) + update_services = self.service_line_ids.filtered( + lambda r: r.is_board_service == True + ) + for service in update_services: + service.onchange_product_calc_qty() + + """ COMPUTE RESERVE COLOR ---------------------------------------------- """ diff --git a/hotel/models/hotel_service.py b/hotel/models/hotel_service.py index 218659dda..52dcc4f7c 100644 --- a/hotel/models/hotel_service.py +++ b/hotel/models/hotel_service.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, api +from odoo import models, fields, api, _ from odoo.tools import DEFAULT_SERVER_DATE_FORMAT from datetime import timedelta from odoo.exceptions import ValidationError @@ -10,6 +10,28 @@ class HotelService(models.Model): _name = 'hotel.service' _description = 'Hotel Services and its charges' + @api.model + def name_search(self, name='', args=None, operator='ilike', limit=100): + if args is None: + args = [] + if not(name == '' and operator == 'ilike'): + args += [ + '|', + ('ser_room_line.name', operator, name), + ('name', operator, name) + ] + return super(HotelService, self).name_search( + name='', args=args, operator='ilike', limit=limit) + + @api.multi + def name_get(self): + result = [] + for res in self: + name = u'%s (%s)' % (res.name, res.ser_room_line.name) + result.append((res.id, name)) + return result + + @api.model def _default_ser_room_line(self): if self.env.context.get('room_lines'): @@ -27,6 +49,7 @@ class HotelService(models.Model): service_line_ids = fields.One2many('hotel.service.line', 'service_id') product_qty = fields.Integer('Quantity') days_qty = fields.Integer(compute="_compute_days_qty", store=True) + is_board_service = fields.Boolean() pricelist_id = fields.Many2one(related='folio_id.pricelist_id') channel_type = fields.Selection([ ('door', 'Door'), @@ -53,7 +76,7 @@ class HotelService(models.Model): @api.model def create(self, vals): if self.compute_lines_out_vals(vals): - reservation = self.env['hotel.reservation'].browse(vals['reservation_id']) + reservation = self.env['hotel.reservation'].browse(vals['ser_room_line']) product = self.env['product.product'].browse(vals['product_id']) params = { 'per_person': product.per_person, @@ -61,7 +84,7 @@ class HotelService(models.Model): } vals.update(self.prepare_service_lines( reservation.checkin, - reservation.days, + reservation.nights, params )) record = super(HotelService, self).create(vals) @@ -80,15 +103,15 @@ class HotelService(models.Model): else: for record in self: reservations = self.env['hotel.reservation'] - reservation = reservations.browse(vals['reservation_id']) \ - if 'reservation_id' in vals else record.reservation_id + reservation = reservations.browse(vals['ser_room_line']) \ + if 'ser_room_line' in vals else record.ser_room_line params = { 'per_person': product.per_person, 'persons': reservation.adults } record.update(record.prepare_service_lines( reservation.checkin, - reservation.days, + reservation.nights, params )) res = super(HotelService, self).write(vals) diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index cb67aa58f..14301499d 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -245,6 +245,7 @@ + - + + + + + +
From b9f18dfd08ee4c5a8ed4acddc54a0138d5df16cb Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Mon, 26 Nov 2018 12:06:43 +0100 Subject: [PATCH 3/5] [ADD] Demo data Board Services and user groups --- hotel/data/hotel_demo.xml | 66 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 61 insertions(+), 5 deletions(-) diff --git a/hotel/data/hotel_demo.xml b/hotel/data/hotel_demo.xml index f2a03e493..60cbf27de 100644 --- a/hotel/data/hotel_demo.xml +++ b/hotel/data/hotel_demo.xml @@ -2,6 +2,16 @@ + + + + + + + + + + @@ -57,8 +67,6 @@ - - @@ -171,7 +179,6 @@ 5.0 service False - True True True @@ -181,7 +188,6 @@ 15.0 service False - True False True 1 @@ -192,11 +198,61 @@ 10.0 service False - True False False + + Menú A + 15.0 + service + False + True + True + + + + Menú B + 20.0 + service + False + True + True + + + + Menú C + 25.0 + service + False + True + True + + + + + + BreakFast + + 0 + + + + Half Board + + 10 + + + + FullBoard + + 10 + + From 05d3814c599acef3ca764508ccf7bf955e498ad3 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Mon, 26 Nov 2018 12:07:17 +0100 Subject: [PATCH 4/5] [IMP] Change service_line_ids in reservation and folio by service_ids --- hotel/models/hotel_folio.py | 2 +- hotel/models/hotel_reservation.py | 16 ++++++++-------- hotel/views/hotel_folio_views.xml | 6 +++--- hotel/views/hotel_reservation_views.xml | 4 ++-- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/hotel/models/hotel_folio.py b/hotel/models/hotel_folio.py index 26f0c5c66..7dba397b6 100644 --- a/hotel/models/hotel_folio.py +++ b/hotel/models/hotel_folio.py @@ -74,7 +74,7 @@ class HotelFolio(models.Model): states={'done': [('readonly', True)]}, help="Hotel room reservation detail.",) - service_line_ids = fields.One2many('hotel.service', 'folio_id', + service_ids = fields.One2many('hotel.service', 'folio_id', readonly=False, states={'done': [('readonly', True)]}, help="Hotel services detail provide to " diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index b950af86e..e6178463a 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -102,7 +102,7 @@ class HotelReservation(models.Model): for record in self: if record.folio_id: record.shared_folio = len(record.folio_id.room_lines) > 1 or \ - any(record.folio_id.service_line_ids.filtered( + any(record.folio_id.service_ids.filtered( lambda x: x.ser_room_line.id != record.id)) @api.depends('checkin', 'checkout') @@ -174,7 +174,7 @@ class HotelReservation(models.Model): store=True) reserve_color_text = fields.Char(compute='_compute_color', string='Color', store=True) - service_line_ids = fields.One2many('hotel.service', 'ser_room_line') + service_ids = fields.One2many('hotel.service', 'ser_room_line') pricelist_id = fields.Many2one('product.pricelist', related='folio_id.pricelist_id', @@ -323,7 +323,7 @@ class HotelReservation(models.Model): days_diff, vals=vals)) #REVISAR el unlink if record.compute_qty_service_day(vals): - for service in record.service_line_ids: + for service in record.service_ids: if service.product_id.per_day: params = { 'per_person': service.product_id.per_person, @@ -349,7 +349,7 @@ class HotelReservation(models.Model): self.ensure_one() if not vals: vals = {} - if 'service_line_ids' in vals: + if 'service_ids' in vals: return False if ('checkin' in vals and self.checkin != vals['checkin']) or \ ('checkout' in vals and self.checkout != vals['checkout']) or \ @@ -537,7 +537,7 @@ class HotelReservation(models.Model): @api.onchange('checkin', 'checkout') def onchange_update_service_per_day(self): - services = self.service_line_ids.filtered(lambda r: r.per_day == True) + services = self.service_ids.filtered(lambda r: r.per_day == True) for service in services: service.onchange_product_calc_qty() @@ -567,7 +567,7 @@ class HotelReservation(models.Model): @api.onchange('board_service_id') def onchange_board_service(self): if self.board_service_id: - self.service_line_ids.filtered(lambda r: r.is_board_service == True).unlink() + self.service_ids.filtered(lambda r: r.is_board_service == True).unlink() board_services = [] for product in self.board_service_id.service_ids: board_services.append((0, False, { @@ -575,8 +575,8 @@ class HotelReservation(models.Model): 'is_board_service': True, })) # NEED REVIEW: Why I need add manually the old IDs if board service is (0,0,(-)) ¿?¿?¿ - self.update({'service_line_ids': [(6, 0, self.service_line_ids.ids)] + board_services}) - update_services = self.service_line_ids.filtered( + self.update({'service_ids': [(6, 0, self.service_ids.ids)] + board_services}) + update_services = self.service_ids.filtered( lambda r: r.is_board_service == True ) for service in update_services: diff --git a/hotel/views/hotel_folio_views.xml b/hotel/views/hotel_folio_views.xml index 5f33d8a2e..bec9ab38f 100644 --- a/hotel/views/hotel_folio_views.xml +++ b/hotel/views/hotel_folio_views.xml @@ -338,7 +338,7 @@ - @@ -407,7 +407,7 @@ - @@ -509,7 +509,7 @@ - + diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index 14301499d..eb9d68eb1 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -239,9 +239,9 @@ - - + From 028d1fcf0da5fba915d197e99e5c811e3f342b97 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Tue, 4 Dec 2018 13:42:51 +0100 Subject: [PATCH 5/5] [ADD] Compute service_ids based in board_service selection --- hotel/data/hotel_demo.xml | 3 + hotel/models/hotel_reservation.py | 84 +++++++++++++++++------ hotel/models/hotel_service.py | 60 ++++++++-------- hotel/models/inherited_account_invoice.py | 3 + 4 files changed, 97 insertions(+), 53 deletions(-) diff --git a/hotel/data/hotel_demo.xml b/hotel/data/hotel_demo.xml index 60cbf27de..2f4cd2427 100644 --- a/hotel/data/hotel_demo.xml +++ b/hotel/data/hotel_demo.xml @@ -265,6 +265,7 @@ 'checkout': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'), 'adults': 2, 'state': 'confirm', + 'board_service_id': ref('hotel_board_service_1'), })]"/> @@ -276,6 +277,7 @@ 'checkin': (DateTime.today() + timedelta(days=2)).strftime('%Y-%m-%d'), 'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'), 'adults': 3, + 'board_service_id': ref('hotel_board_service_2'), })]"/> @@ -312,6 +314,7 @@ 'checkout': (DateTime.today() + timedelta(days=4)).strftime('%Y-%m-%d'), 'adults': 1, 'state': 'confirm', + 'board_service_id': ref('hotel_board_service_1'), })]"/> diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index e6178463a..8406eee33 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -290,6 +290,15 @@ class HotelReservation(models.Model): #~ 'reserve_color': colors[0], #~ 'reserve_color_text': colors[1], }) + if 'board_service_id' in vals: + board_services = [] + board = self.env['hotel.board.service'].browse(vals['board_service_id']) + for product in board.service_ids: + board_services.append((0, False, { + 'product_id': product.id, + 'is_board_service': True, + })) + vals.update({'service_ids': board_services}) if self.compute_price_out_vals(vals): days_diff = ( fields.Date.from_string(vals['checkout']) - fields.Date.from_string(vals['checkin']) @@ -317,6 +326,22 @@ class HotelReservation(models.Model): fields.Date.from_string(checkout) - \ fields.Date.from_string(checkin) ).days + if self.compute_board_services(vals): + record.service_ids.filtered(lambda r: r.is_board_service == True).unlink() + board_services = [] + board = self.env['hotel.board.service'].browse(vals['board_service_id']) + for product in board.service_ids: + board_services.append((0, False, { + 'product_id': product.id, + 'is_board_service': True, + })) + # NEED REVIEW: Why I need add manually the old IDs if board service is (0,0,(-)) ¿?¿?¿ + record.update({'service_ids': [(6, 0, record.service_ids.ids)] + board_services}) + update_services = record.service_ids.filtered( + lambda r: r.is_board_service == True + ) + for service in update_services: + service.onchange_product_calc_qty() if record.compute_price_out_vals(vals): record.update(record.prepare_reservation_lines( checkin, @@ -325,14 +350,12 @@ class HotelReservation(models.Model): if record.compute_qty_service_day(vals): for service in record.service_ids: if service.product_id.per_day: - params = { - 'per_person': service.product_id.per_person, - 'persons': vals['adults'] if 'adults' in vals else record.adults - } service.update(service.prepare_service_lines( - checkin, - days_diff, - params + dfrom=checkin, + days=days_diff, + per_person=product.per_person, + persons=reservation.adults, + old_line_days=service.service_line_ids )) if ('checkin' in vals and record.checkin != vals['checkin']) or \ ('checkout' in vals and record.checkout != vals['checkout']) or \ @@ -341,6 +364,21 @@ class HotelReservation(models.Model): res = super(HotelReservation, self).write(vals) return res + @api.multi + def compute_board_services(self, vals): + """ + We must compute service_ids when we hace a board_service_id without + service_ids associated to reservation + """ + if 'board_service_id' in vals: + if 'service_ids' in vals: + for service in vals['service_ids']: + if 'is_board_service' in service[2] and \ + service[2]['is_board_service'] == True: + return False + return True + return False + @api.multi def compute_qty_service_day(self, vals): """ @@ -361,12 +399,14 @@ class HotelReservation(models.Model): def _prepare_add_missing_fields(self, values): """ Deduce missing required fields from the onchange """ res = {} - onchange_fields = ['room_id', 'reservation_type', 'currency_id', 'name'] + onchange_fields = ['room_id', 'reservation_type', + 'currency_id', 'name', 'board_service_id'] if values.get('room_type_id'): line = self.new(values) if any(f not in values for f in onchange_fields): line.onchange_room_id() line.onchange_compute_reservation_description() + line.onchange_board_service() if 'pricelist_id' not in values: line.onchange_partner_id() for field in onchange_fields: @@ -567,21 +607,23 @@ class HotelReservation(models.Model): @api.onchange('board_service_id') def onchange_board_service(self): if self.board_service_id: - self.service_ids.filtered(lambda r: r.is_board_service == True).unlink() board_services = [] for product in self.board_service_id.service_ids: - board_services.append((0, False, { - 'product_id': product.id, - 'is_board_service': True, - })) - # NEED REVIEW: Why I need add manually the old IDs if board service is (0,0,(-)) ¿?¿?¿ - self.update({'service_ids': [(6, 0, self.service_ids.ids)] + board_services}) - update_services = self.service_ids.filtered( - lambda r: r.is_board_service == True - ) - for service in update_services: - service.onchange_product_calc_qty() - + if product.per_day: + vals = { + 'product_id': product.id, + 'is_board_service': True, + } + vals.update(self.env['hotel.service'].prepare_service_lines( + dfrom=self.checkin, + days=self.nights, + per_person=product.per_person, + persons=self.adults, + old_line_days=False)) + board_services.append((0, False, vals)) + other_services = self.service_ids.filtered(lambda r: r.is_board_service == False) + + self.update({'service_ids': [(6, 0, other_services.ids)] + board_services}) """ COMPUTE RESERVE COLOR ---------------------------------------------- diff --git a/hotel/models/hotel_service.py b/hotel/models/hotel_service.py index 52dcc4f7c..26c52c7b6 100644 --- a/hotel/models/hotel_service.py +++ b/hotel/models/hotel_service.py @@ -78,14 +78,13 @@ class HotelService(models.Model): if self.compute_lines_out_vals(vals): reservation = self.env['hotel.reservation'].browse(vals['ser_room_line']) product = self.env['product.product'].browse(vals['product_id']) - params = { - 'per_person': product.per_person, - 'persons': reservation.adults - } + vals.update(self.prepare_service_lines( - reservation.checkin, - reservation.nights, - params + dfrom=reservation.checkin, + days=reservation.nights, + per_person=product.per_person, + persons=reservation.adults, + old_day_lines=False, )) record = super(HotelService, self).create(vals) return record @@ -105,14 +104,12 @@ class HotelService(models.Model): reservations = self.env['hotel.reservation'] reservation = reservations.browse(vals['ser_room_line']) \ if 'ser_room_line' in vals else record.ser_room_line - params = { - 'per_person': product.per_person, - 'persons': reservation.adults - } record.update(record.prepare_service_lines( - reservation.checkin, - reservation.nights, - params + dfrom=reservation.checkin, + days=reservation.nights, + per_person=product.per_person, + persons=reservation.adults, + old_line_days=self.service_line_ids )) res = super(HotelService, self).write(vals) return res @@ -142,37 +139,36 @@ class HotelService(models.Model): if record.per_day and record.ser_room_line: product = record.product_id reservation = record.ser_room_line - params = { - 'per_person': product.per_person, - 'persons': reservation.adults - } record.update(self.prepare_service_lines( - reservation.checkin, - reservation.nights, - params)) - @api.multi - def prepare_service_lines(self, dfrom, days, params=False): + dfrom=reservation.checkin, + days=reservation.nights, + per_person=product.per_person, + persons=reservation.adults, + old_line_days=self.service_line_ids)) + + @api.model + def prepare_service_lines(self, **kwargs): """ - Respect the old manual changes on lines + Prepare line and respect the old manual changes on lines """ - self.ensure_one() cmds = [(5, 0, 0)] - old_lines_days = self.mapped('service_line_ids.date') + old_lines_days = kwargs.get('old_lines_days') total_qty = 0 day_qty = 1 - if params.get('per_person'): #WARNING: Change adults in reservation NOT update qty service!! - day_qty = params.get('persons') - for i in range(0, days): - idate = (fields.Date.from_string(dfrom) + timedelta(days=i)).strftime( + if kwargs.get('per_person'): #WARNING: Change adults in reservation NOT update qty service!! + day_qty = kwargs.get('persons') + old_line_days = self.env['hotel.service.line'].browse(kwargs.get('old_line_days')) + for i in range(0, kwargs.get('days')): + idate = (fields.Date.from_string(kwargs.get('dfrom')) + timedelta(days=i)).strftime( DEFAULT_SERVER_DATE_FORMAT) - old_line = self.service_line_ids.filtered(lambda r: r.date == idate) - if idate not in old_lines_days: + if not old_lines_days or idate not in old_lines_days.mapped('date'): cmds.append((0, False, { 'date': idate, 'day_qty': day_qty })) total_qty = total_qty + day_qty else: + old_line = old_line_days.filtered(lambda r: r.date == idate) cmds.append((4, old_line.id)) total_qty = total_qty + old_line.day_qty return {'service_line_ids': cmds, 'product_qty': total_qty} diff --git a/hotel/models/inherited_account_invoice.py b/hotel/models/inherited_account_invoice.py index e0e951f07..be8626210 100644 --- a/hotel/models/inherited_account_invoice.py +++ b/hotel/models/inherited_account_invoice.py @@ -58,6 +58,8 @@ class AccountInvoice(models.Model): @api.multi def action_invoice_open(self): + #TODO: VAT Control + """ to_open_invoices_without_vat = self.filtered( lambda inv: inv.state != 'open' and inv.partner_id.vat == False) if to_open_invoices_without_vat: @@ -65,5 +67,6 @@ class AccountInvoice(models.Model): for invoice in to_open_invoices_without_vat: vat_error += ", " + invoice.partner_id.name raise ValidationError(vat_error) + """ return super(AccountInvoice, self).action_invoice_open()