diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index 18d7d81d9..1c1d1218b 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -103,7 +103,7 @@ class HotelReservation(models.Model): if record.folio_id: record.shared_folio = len(record.folio_id.room_lines) > 1 or \ any(record.folio_id.service_line_ids.filtered( - lambda x: x.ser_room_line != record.id)) + lambda x: x.ser_room_line.id != record.id)) @api.depends('checkin', 'checkout') def _computed_nights(self): @@ -310,25 +310,52 @@ class HotelReservation(models.Model): 'last_updated_res': fields.Datetime.now() }) for record in self: + checkin = vals['checkin'] if 'checkin' in vals else record.checkin + checkout = vals['checkout'] if 'checkout' in vals else record.checkout + days_diff = ( + fields.Date.from_string(checkout) - \ + fields.Date.from_string(checkin) + ).days if record.compute_price_out_vals(vals): - checkin = vals['checkin'] if 'checkin' in vals else record.checkin - checkout = vals['checkout'] if 'checkout' in vals else record.checkout - - days_diff = ( - fields.Date.from_string(checkout) - \ - fields.Date.from_string(checkin) - ).days record.update(record.prepare_reservation_lines( - vals['checkin'], + checkin, days_diff, vals=vals)) #REVISAR el unlink + if record.compute_qty_service_day(vals): + for service in record.service_line_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 + )) if ('checkin' in vals and record.checkin != vals['checkin']) or \ - ('checkout' in vals and record.checkout != vals['checkout']) or \ - ('state' in vals and record.state != vals['state']): - vals.update({'to_send': True}) + ('checkout' in vals and record.checkout != vals['checkout']) or \ + ('state' in vals and record.state != vals['state']): + record.update({'to_send': True}) res = super(HotelReservation, self).write(vals) return res + @api.multi + def compute_qty_service_day(self, vals): + """ + Compute if It is necesary calc price in write/create + """ + self.ensure_one() + if not vals: + vals = {} + if 'service_line_ids' in vals: + return False + if ('checkin' in vals and self.checkin != vals['checkin']) or \ + ('checkout' in vals and self.checkout != vals['checkout']) or \ + ('adults' in vals and self.checkout != vals['adults']): + return True + return False + @api.model def _prepare_add_missing_fields(self, values): """ Deduce missing required fields from the onchange """ @@ -507,6 +534,12 @@ class HotelReservation(models.Model): self.name = self.room_type_id.name + ': ' + checkin_str + ' - '\ + checkout_str + @api.onchange('checkin', 'checkout') + def onchange_update_service_per_day(self): + services = self.service_line_ids.filtered(lambda r: r.per_day == True) + for service in services: + service.onchange_product_calc_qty() + @api.multi @api.onchange('checkin', 'checkout', 'room_id') def onchange_room_availabiltiy_domain(self): @@ -748,7 +781,8 @@ class HotelReservation(models.Model): #~ pricelist_id = vals.get('pricelist_id') or self.pricelist_id.id room_type_id = vals.get('room_type_id') or self.room_type_id.id product = self.env['hotel.room.type'].browse(room_type_id).product_id - old_lines_days = self.mapped('reservation_line_ids.date') + old_lines_days = self.mapped('reservation_line_ids.date') #TODO: This is a + # PROBLEM when self is multirecord and the records has different old lines partner = self.env['res.partner'].browse(vals.get('partner_id') or self.partner_id.id) for i in range(0, days): idate = (fields.Date.from_string(dfrom) + timedelta(days=i)).strftime( diff --git a/hotel/models/hotel_service.py b/hotel/models/hotel_service.py index 23c434e88..218659dda 100644 --- a/hotel/models/hotel_service.py +++ b/hotel/models/hotel_service.py @@ -4,6 +4,7 @@ from odoo import models, fields, api from odoo.tools import DEFAULT_SERVER_DATE_FORMAT from datetime import timedelta +from odoo.exceptions import ValidationError class HotelService(models.Model): _name = 'hotel.service' @@ -22,8 +23,10 @@ class HotelService(models.Model): folio_id = fields.Many2one('hotel.folio', 'Folio', ondelete='cascade') ser_room_line = fields.Many2one('hotel.reservation', 'Room', default=_default_ser_room_line) + per_day = fields.Boolean(related='product_id.per_day') 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) pricelist_id = fields.Many2one(related='folio_id.pricelist_id') channel_type = fields.Selection([ ('door', 'Door'), @@ -47,53 +50,95 @@ class HotelService(models.Model): store=True, compute='_compute_amount_reservation') + @api.model + def create(self, vals): + if self.compute_lines_out_vals(vals): + reservation = self.env['hotel.reservation'].browse(vals['reservation_id']) + 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.days, + params + )) + record = super(HotelService, self).create(vals) + return record + + @api.multi + def write(self, vals): + #If you write product, We must check if its necesary create or delete + #service lines + if vals.get('product_id'): + product = self.env['product.product'].browse(vals.get('product_id')) + if not product.per_day: + vals.update({ + 'service_line_ids' : [(5, 0, 0)] + }) + 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 + params = { + 'per_person': product.per_person, + 'persons': reservation.adults + } + record.update(record.prepare_service_lines( + reservation.checkin, + reservation.days, + params + )) + res = super(HotelService, self).write(vals) + return res + + @api.multi + def compute_lines_out_vals(self, vals): + """ + Compute if It is necesary service days in write/create + """ + if not vals: + vals = {} + if 'product_id' in vals: + product = self.env['product.product'].browse(vals['product_id']) \ + if 'product_id' in vals else self.product_id + if (product.per_day and 'service_line_ids' not in vals): + return True + return False + @api.onchange('product_id') def onchange_product_calc_qty(self): """ Compute the default quantity according to the - configuration of the selected product + configuration of the selected product, in per_day product configuration, + the qty is autocalculated and readonly based on service_lines qty """ for record in self: - product = record.product_id - reservation = record.ser_room_line - if product and reservation: - qty = 1 - if product.per_day: - qty = qty * reservation.nights - if product.per_person: - qty = qty * (reservation.adults + reservation.children) - record.product_qty = qty - - @api.onchange('product_qty') - def onchange_product_qty_days_selection(self): - """ - Try to calculate the days on which the product - should be served as long as the product is per day - """ - for record in self: - reservation = record.ser_room_line - if record.product_id.per_day: - days_diff = ( - fields.Date.from_string(reservation.checkout) - fields.Date.from_string(reservation.checkin) - ).days - record.update(record.prepare_service_lines( - reservation.checkin, - days_diff)) - else: - record.update(record.prepare_service_lines( - reservation.checkin, 1)) - - ##WIP## + 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, vals=False): + def prepare_service_lines(self, dfrom, days, params=False): + """ + Respect the old manual changes on lines + """ self.ensure_one() - old_qty = 0 cmds = [(5, 0, 0)] old_lines_days = self.mapped('service_line_ids.date') - for day in self.service_line_ids: - old_qty = old_qty + day.day_qty - qty_day = (self.product_qty - old_qty) // (days - len(old_line_days)) - rest_day = (self.product_qty - old_qty) % (days - len(old_line_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( DEFAULT_SERVER_DATE_FORMAT) @@ -101,11 +146,13 @@ class HotelService(models.Model): if idate not in old_lines_days: cmds.append((0, False, { 'date': idate, - 'day_qty': qty_day + 'day_qty': day_qty })) + total_qty = total_qty + day_qty else: cmds.append((4, old_line.id)) - return {'service_line_ids': cmds} + total_qty = total_qty + old_line.day_qty + return {'service_line_ids': cmds, 'product_qty': total_qty} @api.depends('qty_product', 'tax_id') def _compute_amount_service(self): @@ -121,3 +168,25 @@ class HotelService(models.Model): 'price_total': taxes['total_included'], 'price_subtotal': taxes['total_excluded'], }) + + @api.depends('service_line_ids.day_qty') + def _compute_days_qty(self): + for record in self: + if record.per_day: + qty = sum(record.service_line_ids.mapped('day_qty')) + vals = { + 'days_qty': qty, + 'product_qty': qty + } + else: + vals = {'days_qty': 0} + record.update(vals) + + @api.constrains('qty_product') + def constrains_qty_per_day(self): + for record in self: + if record.per_day: + service_lines = self.env['hotel.service_line'] + total_day_qty = sum(service_lines.with_context({'service_id': record.id}).mapped('day_qty')) + if record.qty_product != total_day_qty: + raise ValidationError (_('The quantity per line and per day does not correspond')) diff --git a/hotel/models/hotel_service_line.py b/hotel/models/hotel_service_line.py index 0e5a2e978..94956c6e2 100644 --- a/hotel/models/hotel_service_line.py +++ b/hotel/models/hotel_service_line.py @@ -26,7 +26,6 @@ class HotelServiceLine(models.Model): if limit < out_qty + record.day_qty: raise ValidationError( _("Limit exceeded for %s")% record.date) - diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index ac02f2a62..4302f78ab 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -239,33 +239,38 @@ - + + - - - - - - - - - - - + + + +
+ + + + + + + + + + + + + +
diff --git a/hotel/views/hotel_service_line_views.xml b/hotel/views/hotel_service_line_views.xml index 6f77df65c..ad7d39ed4 100644 --- a/hotel/views/hotel_service_line_views.xml +++ b/hotel/views/hotel_service_line_views.xml @@ -8,51 +8,33 @@ hotel.service.line
- - - - - - - - - - - - - - - - - - - - - + + + + +
- + hotel.service.line.tree hotel.service.line - + - + + - + Hotel Services hotel.service.line form - tree,form diff --git a/hotel/views/hotel_service_views.xml b/hotel/views/hotel_service_views.xml index e3741c27b..563db4faf 100644 --- a/hotel/views/hotel_service_views.xml +++ b/hotel/views/hotel_service_views.xml @@ -6,58 +6,26 @@ .hotel.service.form hotel.service -
+

- + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + +
@@ -68,10 +36,10 @@ hotel.service.search hotel.service - + - - + +