[ADD] Wizard reservations with Board Services

This commit is contained in:
Dario Lodeiros
2019-03-16 19:18:33 +01:00
parent 682cb584f0
commit eebd1e10dc
4 changed files with 110 additions and 71 deletions

View File

@@ -342,7 +342,7 @@ class HotelReservation(models.Model):
folio = self.env["hotel.folio"].browse(vals['folio_id']) folio = self.env["hotel.folio"].browse(vals['folio_id'])
vals.update({'channel_type': folio.channel_type}) vals.update({'channel_type': folio.channel_type})
elif 'partner_id' in vals: elif 'partner_id' in vals:
folio_vals = {'partner_id':int(vals.get('partner_id')), folio_vals = {'partner_id': int(vals.get('partner_id')),
'channel_type': vals.get('channel_type')} 'channel_type': vals.get('channel_type')}
# Create the folio in case of need (To allow to create reservations direct) # Create the folio in case of need (To allow to create reservations direct)
folio = self.env["hotel.folio"].create(folio_vals) folio = self.env["hotel.folio"].create(folio_vals)
@@ -441,8 +441,8 @@ class HotelReservation(models.Model):
if 'service_ids' in vals: if 'service_ids' in vals:
for service in vals['service_ids']: for service in vals['service_ids']:
if 'is_board_service' in service[2] and \ if 'is_board_service' in service[2] and \
service[2]['is_board_service'] == True: service[2]['is_board_service'] is True:
return False return False
return True return True
return False return False
@@ -728,6 +728,7 @@ class HotelReservation(models.Model):
'product_id': product.id, 'product_id': product.id,
'is_board_service': True, 'is_board_service': True,
'folio_id': self.folio_id.id, 'folio_id': self.folio_id.id,
'ser_room_line': self.id,
} }
line = self.env['hotel.service'].new(res) line = self.env['hotel.service'].new(res)
res.update(self.env['hotel.service']._prepare_add_missing_fields(res)) res.update(self.env['hotel.service']._prepare_add_missing_fields(res))
@@ -738,10 +739,10 @@ class HotelReservation(models.Model):
persons=self.adults, persons=self.adults,
old_line_days=False)) old_line_days=False))
board_services.append((0, False, res)) board_services.append((0, False, res))
other_services = self.service_ids.filtered(lambda r: r.is_board_service == False) other_services = self.service_ids.filtered(lambda r: not r.is_board_service)
self.update({'service_ids': board_services}) self.update({'service_ids': board_services})
self.service_ids |= other_services self.service_ids |= other_services
for service in self.service_ids.filtered(lambda r: r.is_board_service == True): for service in self.service_ids.filtered(lambda r: r.is_board_service):
service._compute_tax_ids() service._compute_tax_ids()
service.price_unit = service._compute_price_unit() service.price_unit = service._compute_price_unit()

View File

@@ -209,7 +209,7 @@ class HotelService(models.Model):
def _prepare_add_missing_fields(self, values): def _prepare_add_missing_fields(self, values):
""" Deduce missing required fields from the onchange """ """ Deduce missing required fields from the onchange """
res = {} res = {}
onchange_fields = ['price_unit','tax_ids','name'] onchange_fields = ['price_unit', 'tax_ids', 'name']
if values.get('product_id'): if values.get('product_id'):
line = self.new(values) line = self.new(values)
if any(f not in values for f in onchange_fields): if any(f not in values for f in onchange_fields):
@@ -317,7 +317,7 @@ class HotelService(models.Model):
self.ensure_one() self.ensure_one()
folio = self.folio_id or self.env.context.get('default_folio_id') folio = self.folio_id or self.env.context.get('default_folio_id')
reservation = self.ser_room_line or self.env.context.get('ser_room_line') reservation = self.ser_room_line or self.env.context.get('ser_room_line')
origin = folio if folio else reservation origin = reservation if reservation else folio
if origin: if origin:
partner = origin.partner_id partner = origin.partner_id
pricelist = origin.pricelist_id pricelist = origin.pricelist_id

View File

@@ -76,8 +76,12 @@ class FolioWizard(models.TransientModel):
'folio_wizard_id', 'folio_wizard_id',
string='Services') string='Services')
total = fields.Float('Total', compute='_computed_total') total = fields.Float('Total', compute='_computed_total')
date_order = fields.Date('Date Order', default=fields.Datetime.now)
confirm = fields.Boolean('Confirm Reservations', default="1") confirm = fields.Boolean('Confirm Reservations', default="1")
autoassign = fields.Boolean('Autoassign', default="1") autoassign = fields.Boolean('Autoassign', default="1")
company_id = fields.Many2one('res.company',
'Company',
default=lambda self: self.env['res.company']._company_default_get('hotel.folio.wizard'))
channel_type = fields.Selection([ channel_type = fields.Selection([
('door', 'Door'), ('door', 'Door'),
('mail', 'Mail'), ('mail', 'Mail'),
@@ -99,16 +103,21 @@ class FolioWizard(models.TransientModel):
@api.onchange('partner_id') @api.onchange('partner_id')
def onchange_partner_id(self): def onchange_partner_id(self):
if self.partner_id: if self.partner_id:
vals = {}
pricelist = self.partner_id.property_product_pricelist and \ pricelist = self.partner_id.property_product_pricelist and \
self.partner_id.property_product_pricelist.id or \ self.partner_id.property_product_pricelist.id or \
self.env['ir.default'].sudo().get( self.env['ir.default'].sudo().get(
'res.config.settings', 'default_pricelist_id') 'res.config.settings', 'default_pricelist_id')
self.pricelist_id = pricelist vals.update({
'pricelist_id': pricelist,
'email': self.partner_id.email,
'mobile': self.partner_id.mobile
})
self.update(vals)
@api.onchange('autoassign') @api.onchange('autoassign')
def create_reservations(self): def create_reservations(self):
self.ensure_one() self.ensure_one()
total = 0
cmds = [] cmds = []
for line in self.room_type_wizard_ids: for line in self.room_type_wizard_ids:
if line.rooms_num == 0: if line.rooms_num == 0:
@@ -133,24 +142,9 @@ class FolioWizard(models.TransientModel):
checkout_dt = fields.Date.from_string(line.checkout) checkout_dt = fields.Date.from_string(line.checkout)
nights = abs((checkout_dt - checkin_dt).days) nights = abs((checkout_dt - checkin_dt).days)
for room in room_list: for room in room_list:
pricelist_id = self.pricelist_id.id
res_price = 0
for i in range(0, nights):
ndate = checkin_dt + timedelta(days=i)
ndate_str = ndate.strftime(DEFAULT_SERVER_DATE_FORMAT)
prod = line.room_type_id.product_id.with_context(
lang=self.partner_id.lang,
partner=self.partner_id.id,
quantity=1,
date=ndate_str,
pricelist=pricelist_id,
uom=room.room_type_id.product_id.uom_id.id)
res_price += prod.price
adults = self.env['hotel.room'].search([ adults = self.env['hotel.room'].search([
('id', '=', room.id) ('id', '=', room.id)
]).capacity ]).capacity
res_price = res_price - (res_price * line.discount)/100
total += res_price
cmds.append((0, False, { cmds.append((0, False, {
'checkin': line.checkin, 'checkin': line.checkin,
'checkout': line.checkout, 'checkout': line.checkout,
@@ -158,13 +152,12 @@ class FolioWizard(models.TransientModel):
'room_id': room.id, 'room_id': room.id,
'nights': nights, 'nights': nights,
'adults': adults, 'adults': adults,
'board_service_room_id': line.board_service_room_id,
'children': 0, 'children': 0,
'room_type_id': line.room_type_id, 'room_type_id': line.room_type_id,
'price': res_price, 'price': line.price,
'amount_reservation': res_price
})) }))
self.reservation_wizard_ids = cmds self.reservation_wizard_ids = cmds
self.total = total
@api.multi @api.multi
@api.onchange('checkin', 'checkout') @api.onchange('checkin', 'checkout')
@@ -202,19 +195,22 @@ class FolioWizard(models.TransientModel):
for room_type in self.room_type_wizard_ids: for room_type in self.room_type_wizard_ids:
room_type.update_price() room_type.update_price()
@api.depends('room_type_wizard_ids', 'reservation_wizard_ids', 'service_wizard_ids') @api.depends('room_type_wizard_ids.total_price',
'reservation_wizard_ids.price',
'reservation_wizard_ids',
'service_wizard_ids.price_total')
def _computed_total(self): def _computed_total(self):
total = 0 total = 0
for line in self.service_wizard_ids: for line in self.service_wizard_ids:
total += line.price_total total += line.price_total
if not self.reservation_wizard_ids: if not self.reservation_wizard_ids:
for line in self.room_type_wizard_ids: for line in self.room_type_wizard_ids:
total += line.total_price total += line.total_price
self.total = total
else: else:
for line in self.reservation_wizard_ids: for line in self.reservation_wizard_ids:
total += line.price total += line.price
self.total = total self.total = total
@api.multi @api.multi
def create_folio(self): def create_folio(self):
@@ -222,7 +218,7 @@ class FolioWizard(models.TransientModel):
if not self.partner_id: if not self.partner_id:
raise ValidationError(_("We need know the customer!")) raise ValidationError(_("We need know the customer!"))
reservations = [(5, False, False)] reservations = [(5, False, False)]
services = [(5, False, False)] services = []
if self.autoassign: if self.autoassign:
self.create_reservations() self.create_reservations()
for line in self.reservation_wizard_ids: for line in self.reservation_wizard_ids:
@@ -234,7 +230,7 @@ class FolioWizard(models.TransientModel):
'checkout': line.checkout, 'checkout': line.checkout,
'discount': line.discount, 'discount': line.discount,
'room_type_id': line.room_type_id.id, 'room_type_id': line.room_type_id.id,
'to_read': line.to_read, 'board_service_room_id': line.board_service_room_id.id,
'to_assign': line.to_assign, 'to_assign': line.to_assign,
})) }))
for line in self.service_wizard_ids: for line in self.service_wizard_ids:
@@ -242,7 +238,7 @@ class FolioWizard(models.TransientModel):
'product_id': line.product_id.id, 'product_id': line.product_id.id,
'discount': line.discount, 'discount': line.discount,
'price_unit': line.price_unit, 'price_unit': line.price_unit,
'product_uom_qty': line.product_uom_qty, 'product_qty': line.product_uom_qty,
})) }))
if not self.reservation_wizard_ids: if not self.reservation_wizard_ids:
raise ValidationError(_('We cant create avoid folio')) raise ValidationError(_('We cant create avoid folio'))
@@ -250,7 +246,8 @@ class FolioWizard(models.TransientModel):
'partner_id': self.partner_id.id, 'partner_id': self.partner_id.id,
'channel_type': self.channel_type, 'channel_type': self.channel_type,
'room_lines': reservations, 'room_lines': reservations,
'service_lines': services, 'service_ids': services,
'pricelist_id': self.pricelist_id.id,
'internal_comment': self.internal_comment, 'internal_comment': self.internal_comment,
'credit_card_details': self.credit_card_details, 'credit_card_details': self.credit_card_details,
'email': self.email, 'email': self.email,
@@ -284,9 +281,10 @@ class HotelRoomTypeWizards(models.TransientModel):
rooms_num = fields.Integer('Number of Rooms') rooms_num = fields.Integer('Number of Rooms')
max_rooms = fields.Integer('Max', compute="_compute_max") max_rooms = fields.Integer('Max', compute="_compute_max")
price = fields.Float(string='Price by Room') price = fields.Float(string='Price by Room')
total_price = fields.Float(string='Total Price') total_price = fields.Float(string='Total Price',
compute="_compute_total",
store="True")
folio_wizard_id = fields.Many2one('hotel.folio.wizard') folio_wizard_id = fields.Many2one('hotel.folio.wizard')
amount_reservation = fields.Float(string='Total', readonly=True)
discount = fields.Float('discount') discount = fields.Float('discount')
min_stay = fields.Integer('Min. Days', compute="_compute_max") min_stay = fields.Integer('Min. Days', compute="_compute_max")
checkin = fields.Date('Check In', required=True, checkin = fields.Date('Check In', required=True,
@@ -354,7 +352,13 @@ class HotelRoomTypeWizards(models.TransientModel):
if min_stay > 0: if min_stay > 0:
res.min_stay = min_stay res.min_stay = min_stay
@api.onchange('rooms_num', 'discount', 'price', 'room_type_id', 'checkin', 'checkout') @api.depends('rooms_num', 'price')
def _compute_total(self):
for res in self:
res.total_price = res.price * res.rooms_num
@api.onchange('rooms_num', 'discount', 'price', 'board_service_room_id',
'room_type_id', 'checkin', 'checkout')
def update_price(self): def update_price(self):
for record in self: for record in self:
if record.rooms_num > record.max_rooms: if record.rooms_num > record.max_rooms:
@@ -380,18 +384,20 @@ class HotelRoomTypeWizards(models.TransientModel):
uom=record.room_type_id.product_id.uom_id.id) uom=record.room_type_id.product_id.uom_id.id)
res_price += product.price res_price += product.price
board_service = record.board_service_room_id
if board_service:
if board_service.price_type == 'fixed':
board_price = board_service.amount *\
record.room_type_id.capacity * nights
res_price += board_price
else:
res_price += ((res_price * board_service.amount) * 0.01)
price = res_price - ((res_price * record.discount) * 0.01) price = res_price - ((res_price * record.discount) * 0.01)
total_price = record.rooms_num * price
vals = { vals = {
'checkin': checkin, 'checkin': checkin,
'checkout': checkout, 'checkout': checkout,
'price': price, 'price': price,
'total_price': total_price,
'amount_reservation': total_price,
} }
_logger.info("NEW VUELTA ________________")
_logger.info(record.room_type_id.name)
_logger.info(vals)
record.update(vals) record.update(vals)
@@ -413,18 +419,18 @@ class ReservationWizard(models.TransientModel):
required=True) required=True)
nights = fields.Integer('Nights', readonly=True) nights = fields.Integer('Nights', readonly=True)
price = fields.Float(string='Total') price = fields.Float(string='Total')
amount_reservation = fields.Float(string='Total', readonly=True)
partner_id = fields.Many2one(related='folio_wizard_id.partner_id') partner_id = fields.Many2one(related='folio_wizard_id.partner_id')
discount = fields.Float('discount') discount = fields.Float('discount')
to_read = fields.Boolean(compute="_compute_to_read_assign") to_assign = fields.Boolean(compute="_compute_assign")
to_assign = fields.Boolean(compute="_compute_to_read_assign") board_service_room_id = fields.Many2one('hotel.board.service.room.type',
string="Board Service")
@api.multi @api.multi
def _compute_to_read_assign(self): def _compute_assign(self):
for rec in self: for rec in self:
user = self.env['res.users'].browse(self.env.uid) user = self.env['res.users'].browse(self.env.uid)
if user.has_group('hotel.group_hotel_call'): if user.has_group('hotel.group_hotel_call'):
rec.to_read = rec.to_assign = True rec.to_assign = True
@api.multi @api.multi
@api.onchange('room_id') @api.onchange('room_id')
@@ -445,7 +451,8 @@ class ReservationWizard(models.TransientModel):
choice other room or change the reservation date")) choice other room or change the reservation date"))
@api.multi @api.multi
@api.onchange('checkin', 'checkout', 'room_type_id', 'discount') @api.onchange('checkin', 'checkout', 'room_type_id',
'discount', 'board_service_room_id')
def onchange_dates(self): def onchange_dates(self):
for line in self: for line in self:
if not self.checkin: if not self.checkin:
@@ -471,8 +478,15 @@ class ReservationWizard(models.TransientModel):
pricelist=pricelist_id, pricelist=pricelist_id,
uom=line.room_type_id.product_id.uom_id.id) uom=line.room_type_id.product_id.uom_id.id)
res_price += product.price res_price += product.price
board_service = line.board_service_room_id
if board_service:
if board_service.price_type == 'fixed':
board_price = board_service.amount *\
line.adults * nights
res_price += board_price
else:
res_price += ((res_price * board_service.amount) * 0.01)
res_price = res_price - (res_price * self.discount) * 0.01 res_price = res_price - (res_price * self.discount) * 0.01
line.amount_reservation = res_price
line.price = res_price line.price = res_price
end_date_utc_dt -= timedelta(days=1) end_date_utc_dt -= timedelta(days=1)
occupied = self.env['hotel.reservation'].get_reservations( occupied = self.env['hotel.reservation'].get_reservations(
@@ -488,13 +502,17 @@ class ServiceWizard(models.TransientModel):
product_id = fields.Many2one('product.product', product_id = fields.Many2one('product.product',
string="Service") string="Service")
name = fields.Char('Description')
folio_wizard_id = fields.Many2one('hotel.folio.wizard') folio_wizard_id = fields.Many2one('hotel.folio.wizard')
discount = fields.Float('discount') discount = fields.Float('discount')
price_unit = fields.Float('Unit Price', required=True, price_unit = fields.Float('Unit Price', required=True,
digits=dp.get_precision('Product Price'), digits=dp.get_precision('Product Price'),
default=0.0) default=0.0)
price_total = fields.Float(compute='_compute_amount', string='Subtotal', price_total = fields.Float(compute='_compute_amount', string='Total',
readonly=True, store=True) readonly=True, store=True)
tax_ids = fields.Many2many('account.tax', string='Taxes',
domain=['|', ('active', '=', False),
('active', '=', True)])
product_uom_qty = fields.Float(string='Quantity', product_uom_qty = fields.Float(string='Quantity',
digits=dp.get_precision('Product Unit of Measure'), digits=dp.get_precision('Product Unit of Measure'),
required=True, required=True,
@@ -503,19 +521,36 @@ class ServiceWizard(models.TransientModel):
@api.onchange('product_id') @api.onchange('product_id')
def onchange_product_id(self): def onchange_product_id(self):
if self.product_id: if self.product_id:
# TODO change pricelist for partner
pricelist_id = self.folio_wizard_id.pricelist_id.id pricelist_id = self.folio_wizard_id.pricelist_id.id
prod = self.product_id.with_context( prod = self.product_id.with_context(
lang=self.folio_wizard_id.partner_id.lang, lang=self.folio_wizard_id.partner_id.lang,
partner=self.folio_wizard_id.partner_id.id, partner=self.folio_wizard_id.partner_id.id,
quantity=1, quantity=1,
date=fields.Datetime.now(), date=fields.Datetime.now(),
pricelist=pricelist_id, pricelist=pricelist_id,
uom=self.product_id.uom_id.id) uom=self.product_id.uom_id.id)
self.price_unit = prod.price # TODO change pricelist for partner
values = {'pricelist_id': pricelist_id, 'product_id': prod.id}
line = self.env['hotel.service'].new(values)
vals = line.with_context({
'default_folio_id': self.folio_wizard_id
})._prepare_add_missing_fields(values)
self.update(vals)
@api.depends('price_unit', 'product_uom_qty', 'discount') @api.depends('product_uom_qty', 'discount', 'price_unit', 'tax_ids')
def _compute_amount(self): def _compute_amount(self):
for ser in self: """
total = (ser.price_unit * ser.product_uom_qty) Compute the amounts of the service line.
ser.price_total = total - (total * ser.discount) * 0.01 """
for record in self:
pricelist = record.folio_wizard_id.pricelist_id
currency = pricelist.currency_id
product = record.product_id
price = record.price_unit * (1 - (record.discount or 0.0) * 0.01)
taxes = record.tax_ids.compute_all(price,
currency,
record.product_uom_qty,
product=product)
record.update({
'price_total': taxes['total_included'],
})

View File

@@ -12,8 +12,9 @@
<field name="checkin" required="1" /> <field name="checkin" required="1" />
<field name="checkout" required="1" /> <field name="checkout" required="1" />
<field name="partner_id"/> <field name="partner_id"/>
<field name="mobile" required="1"/> <field name="mobile" required="1" />
<field name="email" required="1"/> <field name="email" required="1" />
<field name="company_id" invisible="1" />
</group> </group>
<group> <group>
<field name="call_center" invisible="1" /> <field name="call_center" invisible="1" />
@@ -21,6 +22,7 @@
<field name="pricelist_id"/> <field name="pricelist_id"/>
<field name="internal_comment"/> <field name="internal_comment"/>
<field name="credit_card_details" /> <field name="credit_card_details" />
<field name="date_order" invisible="1" />
</group> </group>
</group> </group>
<group> <group>
@@ -32,7 +34,7 @@
decoration-success="max_rooms &gt;= rooms_num and rooms_num &gt; 0"> decoration-success="max_rooms &gt;= rooms_num and rooms_num &gt; 0">
<field name="min_stay" /> <field name="min_stay" />
<field name="max_rooms" /> <field name="max_rooms" />
<field name="folio_wizard_id" /> <field name="folio_wizard_id" invisible="1"/>
<field name="room_type_id" string="Room Type" force_save="1" readonly="1"/> <field name="room_type_id" string="Room Type" force_save="1" readonly="1"/>
<field name="rooms_num" force_save="1" attrs="{'readonly': [('can_confirm', '=', False)]}" /> <field name="rooms_num" force_save="1" attrs="{'readonly': [('can_confirm', '=', False)]}" />
<field name="board_service_room_id" <field name="board_service_room_id"
@@ -42,8 +44,7 @@
<field name="checkout" widget="date" /> <field name="checkout" widget="date" />
<field name="discount" force_save="1" attrs="{'readonly': [('can_confirm','=',False)]}"/> <field name="discount" force_save="1" attrs="{'readonly': [('can_confirm','=',False)]}"/>
<field name="price" force_save="1" attrs="{'readonly': [('can_confirm','=',False)]}"/> <field name="price" force_save="1" attrs="{'readonly': [('can_confirm','=',False)]}"/>
<field name="amount_reservation" force_save="1" readonly="1" /> <field name="total_price" />
<field name="total_price" invisible="1" />
<field name="can_confirm" invisible="1" /> <field name="can_confirm" invisible="1" />
</tree> </tree>
</field> </field>
@@ -65,12 +66,13 @@
<field name="nights" /> <field name="nights" />
<field name="adults" /> <field name="adults" />
<field name="children" /> <field name="children" />
<field name="board_service_room_id" domain="[
('hotel_room_type_id', '=', room_type_id)
]" />
<field name="discount" /> <field name="discount" />
<field name="amount_reservation" /> <field name="price" />
<field name="price" invisible = "1"/>
<field name="partner_id" invisible = "1" /> <field name="partner_id" invisible = "1" />
<field name="folio_wizard_id" invisible = "1" /> <field name="folio_wizard_id" invisible = "1" />
<field name="to_read" invisible="1" />
<field name="to_assign" invisible="1" /> <field name="to_assign" invisible="1" />
</tree> </tree>
</field> </field>
@@ -87,6 +89,7 @@
<field name="product_uom_qty" /> <field name="product_uom_qty" />
<field name="price_unit" /> <field name="price_unit" />
<field name="discount" /> <field name="discount" />
<field name="tax_ids" widget="many2many_tags"/>
<field name="price_total" /> <field name="price_total" />
</tree> </tree>
</field> </field>