From b466d9643b3d44d24cc408986af517bc88f584e1 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Tue, 29 Jan 2019 10:37:29 +0100 Subject: [PATCH 01/15] [WIP] Checkin WorkFlow --- hotel/models/hotel_checkin_partner.py | 41 +++++++++++++++++-- hotel/models/hotel_reservation.py | 12 +++++- hotel/views/hotel_checkin_partner_views.xml | 16 ++++++-- hotel/views/hotel_reservation_views.xml | 6 ++- hotel/wizard/checkinwizard.py | 4 +- .../inherit_hotel_checkin_partner_views.xml | 8 ++-- 6 files changed, 70 insertions(+), 17 deletions(-) diff --git a/hotel/models/hotel_checkin_partner.py b/hotel/models/hotel_checkin_partner.py index 5fe511faa..cc27b8dbe 100644 --- a/hotel/models/hotel_checkin_partner.py +++ b/hotel/models/hotel_checkin_partner.py @@ -23,6 +23,11 @@ class HotelCheckinPartner(models.Model): self.env.context['folio_id'] ]) return folio + if 'reservation_id' in self.env.context: + folio = self.env['hotel.reservation'].browse([ + self.env.context['reservation_id'] + ]).folio_id + return folio return False def _default_enter_date(self): @@ -46,16 +51,21 @@ class HotelCheckinPartner(models.Model): reservation = self.env['hotel.reservation'].browse([ self.env.context['reservation_id'] ]) - return reservation.partner_id + if reservation.partner_id.id not in reservation.mapped( + 'checkin_partner_ids.partner_id.id'): + return reservation.partner_id return False partner_id = fields.Many2one('res.partner', default=_default_partner_id, required=True) + email = fields.Char('E-mail', related='partner_id.email') + mobile = fields.Char('Mobile', related='partner_id.mobile') + gender = fields.Selection('Gender', related='partner_id.gender') reservation_id = fields.Many2one( 'hotel.reservation', default=_default_reservation_id) - folio_id = fields.Many2one('hotel.reservation', - default=_default_folio_id, readonly=True) + folio_id = fields.Many2one('hotel.folio', + default=_default_folio_id, readonly=True, required=True) enter_date = fields.Date(default=_default_enter_date, required=True) exit_date = fields.Date(default=_default_exit_date, required=True) state = fields.Selection([('draft', 'Pending Entry'), @@ -65,6 +75,7 @@ class HotelCheckinPartner(models.Model): 'State', readonly=True, default=lambda *a: 'draft', track_visibility='onchange') + # Validation for Departure date is after arrival date. @api.multi @@ -89,6 +100,30 @@ class HotelCheckinPartner(models.Model): _('Departure date, is prior to arrival. Check it now. %s') % date_out) + @api.multi + @api.onchange('partner_id') + def _check_partner_id(self): + for record in self: + checkins = self.env['hotel.checkin.partner'].search([ + ('id','!=', record.id), + ('reservation_id','=', record.reservation_id.id) + ]) + if record.partner_id.id in checkins.mapped('partner_id.id'): + raise models.ValidationError( + _('This guest is already registered in the room')) + + @api.multi + @api.constrains('partner_id') + def _check_partner_id(self): + for record in self: + checkins = self.env['hotel.checkin.partner'].search([ + ('id','!=', record.id), + ('reservation_id','=', record.reservation_id.id) + ]) + if record.partner_id.id in checkins.mapped('partner_id.id'): + raise models.ValidationError( + _('This guest is already registered in the room')) + @api.multi def action_on_board(self): for record in self: diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index 8eedba68f..220f30056 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -991,12 +991,20 @@ class HotelReservation(models.Model): @api.multi def action_checks(self): self.ensure_one() - return { + partner = self.partner_id.id + reservation_id = self.id + view_id = self.env.ref('hotel.hotel_checkin_partner_reservation_view_tree').id + return{ 'name': _('Checkins'), 'view_type': 'form', - 'view_mode': 'tree,form', + 'view_mode': 'tree', 'res_model': 'hotel.checkin.partner', 'type': 'ir.actions.act_window', + 'view_id': view_id, + 'context': { + 'reservation_id': reservation_id, + }, + 'flags': {'initial_mode': 'edit'}, 'domain': [('reservation_id', '=', self.id)], 'target': 'new', } diff --git a/hotel/views/hotel_checkin_partner_views.xml b/hotel/views/hotel_checkin_partner_views.xml index b19c5ce48..004788d37 100644 --- a/hotel/views/hotel_checkin_partner_views.xml +++ b/hotel/views/hotel_checkin_partner_views.xml @@ -40,7 +40,7 @@ hotel.checkin.partner 20 - @@ -51,10 +51,14 @@ help="Get in" /> + + + - - + + + @@ -75,10 +79,14 @@ help="Get in" /> + + + - + + diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index 43acee8c1..9721c8c98 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -304,6 +304,10 @@ + + + - diff --git a/hotel/wizard/checkinwizard.py b/hotel/wizard/checkinwizard.py index 2ce8cce0b..8bb5b669e 100644 --- a/hotel/wizard/checkinwizard.py +++ b/hotel/wizard/checkinwizard.py @@ -115,8 +115,8 @@ class Wizard(models.TransientModel): mobile_checkin_partner = fields.Char('Mobile') - segmentation_id = fields.Many2many( - related='reservation_id.folio_id.segmentation_ids') + segmentation_ids = fields.Many2many( + related='reservation_id.segmentation_ids') ''' TODO: clean-up - list of checkins on smart button clean is not used anymore diff --git a/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml b/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml index 1293a2c32..0130d1a14 100644 --- a/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml +++ b/hotel_l10n_es/views/inherit_hotel_checkin_partner_views.xml @@ -32,8 +32,8 @@ - - + + @@ -54,8 +54,8 @@ - - + + From e9e25c667ae73a695347540602490e4a44f43e26 Mon Sep 17 00:00:00 2001 From: Dario Lodeiros Date: Tue, 29 Jan 2019 14:05:24 +0100 Subject: [PATCH 02/15] [WIP] Invoice Contact Folio Form --- hotel/models/hotel_folio.py | 47 +++++++++++++++- hotel/models/hotel_reservation.py | 13 ++++- hotel/views/hotel_folio_views.xml | 75 ++++++++++++++++++++----- hotel/views/hotel_reservation_views.xml | 73 +++++++++++++++++------- 4 files changed, 170 insertions(+), 38 deletions(-) diff --git a/hotel/models/hotel_folio.py b/hotel/models/hotel_folio.py index 60fab830d..39b541045 100644 --- a/hotel/models/hotel_folio.py +++ b/hotel/models/hotel_folio.py @@ -34,6 +34,20 @@ class HotelFolio(models.Model): def _compute_qty_delivered_updateable(self): pass + @api.model + def _default_diff_invoicing(self): + """ + If the guest has an invoicing address set, + this method return diff_invoicing = True, else, return False + """ + if 'folio_id' in self.env.context: + folio = self.env['hotel.folio'].browse([ + self.env.context['folio_id'] + ]) + if folio.partner_id.id == folio.partner_invoice_id.id: + return False + return True + @api.depends('state', 'room_lines.invoice_status', 'service_ids.invoice_status') def _get_invoiced(self): """ @@ -211,7 +225,20 @@ class HotelFolio(models.Model): string='Invoice Address', required=True, states={'done': [('readonly', True)]}, help="Invoice address for current sales order.") + partner_invoice_vat = fields.Char(related="partner_invoice_id.vat") + partner_invoice_name = fields.Char(related="partner_invoice_id.name") + partner_invoice_street = fields.Char(related="partner_invoice_id.street") + partner_invoice_street2 = fields.Char(related="partner_invoice_id.street") + partner_invoice_zip = fields.Char(related="partner_invoice_id.zip") + partner_invoice_city = fields.Char(related="partner_invoice_id.city") + partner_invoice_state_id = fields.Many2one(related="partner_invoice_id.state_id") + partner_invoice_country_id = fields.Many2one(related="partner_invoice_id.country_id") + partner_invoice_email = fields.Char(related="partner_invoice_id.email") + partner_invoice_lang = fields.Selection(related="partner_invoice_id.lang") + partner_invoice_type = fields.Selection(related="partner_invoice_id.type") + partner_invoice_parent_id = fields.Many2one(related="partner_invoice_id.parent_id") fiscal_position_id = fields.Many2one('account.fiscal.position', oldname='fiscal_position', string='Fiscal Position') + partner_diff_invoicing = fields.Boolean('Bill to another Address', default='_default_diff_invoicing') #WorkFlow Mail Fields----------------------------------------------- has_confirmed_reservations_to_send = fields.Boolean( @@ -446,18 +473,20 @@ class HotelFolio(models.Model): 'partner_invoice_id': False, 'payment_term_id': False, 'fiscal_position_id': False, + 'partner_diff_invoicing': False, }) return addr = self.partner_id.address_get(['invoice']) pricelist = self.partner_id.property_product_pricelist and \ self.partner_id.property_product_pricelist.id or \ - self.env['ir.default'].sudo().get('res.config.settings', 'default_pricelist_id') + self.env['ir.default'].sudo().get('res.config.settings', 'default_pricelist_id') values = { 'pricelist_id': pricelist, 'payment_term_id': self.partner_id.property_payment_term_id and self.partner_id.property_payment_term_id.id or False, 'partner_invoice_id': addr['invoice'], - 'user_id': self.partner_id.user_id.id or self.env.uid + 'user_id': self.partner_id.user_id.id or self.env.uid, + 'partner_diff_invoicing': False if self.partner_id.id == addr['invoice'] else True } if self.env['ir.config_parameter'].sudo().get_param('sale.use_sale_note') and \ @@ -477,6 +506,20 @@ class HotelFolio(models.Model): self.reservation_type)} self.update(values) + @api.onchange('partner_diff_invoicing') + def onchange_partner_diff_invoicing(self): + if self.partner_diff_invoicing == False: + self.update({'partner_invoice_id': self.partner_id.id}) + elif self.partner_id == self.partner_invoice_id: + self.update({'partner_invoice_id': self.partner_id.address_get(['invoice'])['invoice'] or None}) + + @api.onchange('partner_invoice_id') + def onchange_partner_invoice_id(self): + if self.partner_invoice_id and not self.partner_invoice_id.parent_id and \ + self.partner_invoice_id != self.partner_id: + self.update({ + 'partner_invoice_parent_id': self.partner_id.id, + 'partner_invoice_type': 'invoice'}) @api.model def calcule_reservation_type(self, is_staff, current_type): diff --git a/hotel/models/hotel_reservation.py b/hotel/models/hotel_reservation.py index 220f30056..e6912e74a 100644 --- a/hotel/models/hotel_reservation.py +++ b/hotel/models/hotel_reservation.py @@ -191,6 +191,17 @@ class HotelReservation(models.Model): required=True, track_visibility='onchange') partner_id = fields.Many2one(related='folio_id.partner_id') + partner_invoice_id = fields.Many2one(related='folio_id.partner_invoice_id') + partner_invoice_vat = fields.Char(related="partner_invoice_id.vat") + partner_invoice_name = fields.Char(related="partner_invoice_id.name") + partner_invoice_street = fields.Char(related="partner_invoice_id.street") + partner_invoice_street2 = fields.Char(related="partner_invoice_id.street") + partner_invoice_zip = fields.Char(related="partner_invoice_id.zip") + partner_invoice_city = fields.Char(related="partner_invoice_id.city") + partner_invoice_state_id = fields.Many2one(related="partner_invoice_id.state_id") + partner_invoice_country_id = fields.Many2one(related="partner_invoice_id.country_id") + partner_invoice_email = fields.Char(related="partner_invoice_id.email") + partner_invoice_lang = fields.Selection(related="partner_invoice_id.lang") 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) reservation_line_ids = fields.One2many('hotel.reservation.line', @@ -858,7 +869,7 @@ class HotelReservation(models.Model): def action_pay_reservation(self): self.ensure_one() partner = self.partner_id.id - amount = min(self.amount_reservation, self.folio_pending_amount) + amount = min(self.price_room_services_set, self.folio_pending_amount) note = self.folio_id.name + ' (' + self.name + ')' view_id = self.env.ref('hotel.account_payment_view_form_folio').id return{ diff --git a/hotel/views/hotel_folio_views.xml b/hotel/views/hotel_folio_views.xml index 315445b0d..4d6d92d0b 100644 --- a/hotel/views/hotel_folio_views.xml +++ b/hotel/views/hotel_folio_views.xml @@ -132,7 +132,6 @@ - @@ -150,31 +149,79 @@ + + + + + + +
+ + + - + + nolabel="1" context="{'from_folio':True,'room_lines':room_lines,'folio_id': id,'tree_view_ref':'hotel.hotel_reservation_view_bottom_tree', 'form_view_ref':'hotel.hotel_reservation_view_form'}"/> + + - - - - - - -
+ + - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/hotel/views/hotel_reservation_views.xml b/hotel/views/hotel_reservation_views.xml index 9721c8c98..1617eaf22 100644 --- a/hotel/views/hotel_reservation_views.xml +++ b/hotel/views/hotel_reservation_views.xml @@ -23,24 +23,27 @@ +
- + - - - - - - - - - + + + - - - - -