mirror of
https://github.com/OCA/pms.git
synced 2025-01-29 00:17:45 +02:00
Merge pull request #50 from hootel/hotel_availability_refactoring
Hotel availability refactoring
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,3 +2,4 @@
|
|||||||
|
|
||||||
.settings/
|
.settings/
|
||||||
|
|
||||||
|
.idea
|
||||||
|
|||||||
@@ -4842,7 +4842,7 @@ msgid "Invoices"
|
|||||||
msgstr "Facturas"
|
msgstr "Facturas"
|
||||||
|
|
||||||
#. module: hotel
|
#. module: hotel
|
||||||
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_invoices_amount
|
#: model:ir.model.fields,field_description:hotel.field_hotel_folio_pending_amount
|
||||||
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_folio_pending_amount
|
#: model:ir.model.fields,field_description:hotel.field_hotel_reservation_folio_pending_amount
|
||||||
msgid "Invoices amount"
|
msgid "Invoices amount"
|
||||||
msgstr "Cantidad Facturada"
|
msgstr "Cantidad Facturada"
|
||||||
|
|||||||
@@ -23,50 +23,6 @@ from odoo.addons import decimal_precision as dp
|
|||||||
|
|
||||||
class HotelFolio(models.Model):
|
class HotelFolio(models.Model):
|
||||||
|
|
||||||
@api.model
|
|
||||||
def name_search(self, name='', args=None, operator='ilike', limit=100):
|
|
||||||
if args is None:
|
|
||||||
args = []
|
|
||||||
args += ([('name', operator, name)])
|
|
||||||
mids = self.search(args, limit=100)
|
|
||||||
return mids.name_get()
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def _needaction_count(self, domain=None):
|
|
||||||
"""
|
|
||||||
Show a count of draft state folio on the menu badge.
|
|
||||||
@param self: object pointer
|
|
||||||
"""
|
|
||||||
return self.search_count([('state', '=', 'draft')])
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def copy(self, default=None):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
@param default: dict of default values to be set
|
|
||||||
'''
|
|
||||||
return super(HotelFolio, self).copy(default=default)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _invoiced(self, name, arg):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
@param name: Names of fields.
|
|
||||||
@param arg: User defined arguments
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
# return self.env['sale.order']._invoiced(name, arg)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _invoiced_search(self, obj, name, args):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
@param name: Names of fields.
|
|
||||||
@param arg: User defined arguments
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
# return self.env['sale.order']._invoiced_search(obj, name, args)
|
|
||||||
|
|
||||||
# @api.depends('invoice_lines.invoice_id.state', 'invoice_lines.quantity')
|
# @api.depends('invoice_lines.invoice_id.state', 'invoice_lines.quantity')
|
||||||
def _get_invoice_qty(self):
|
def _get_invoice_qty(self):
|
||||||
pass
|
pass
|
||||||
@@ -93,7 +49,7 @@ class HotelFolio(models.Model):
|
|||||||
_inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin']
|
_inherit = ['mail.thread', 'mail.activity.mixin', 'portal.mixin']
|
||||||
|
|
||||||
name = fields.Char('Folio Number', readonly=True, index=True,
|
name = fields.Char('Folio Number', readonly=True, index=True,
|
||||||
default='New')
|
default=lambda self: _('New'))
|
||||||
partner_id = fields.Many2one('res.partner',
|
partner_id = fields.Many2one('res.partner',
|
||||||
track_visibility='onchange')
|
track_visibility='onchange')
|
||||||
# partner_invoice_id = fields.Many2one('res.partner',
|
# partner_invoice_id = fields.Many2one('res.partner',
|
||||||
@@ -108,6 +64,7 @@ class HotelFolio(models.Model):
|
|||||||
mobile = fields.Char('Mobile', related='partner_id.mobile')
|
mobile = fields.Char('Mobile', related='partner_id.mobile')
|
||||||
phone = fields.Char('Phone', related='partner_id.phone')
|
phone = fields.Char('Phone', related='partner_id.phone')
|
||||||
|
|
||||||
|
#Review: How to use state in folio?
|
||||||
state = fields.Selection([('draft', 'Pre-reservation'), ('confirm', 'Pending Entry'),
|
state = fields.Selection([('draft', 'Pre-reservation'), ('confirm', 'Pending Entry'),
|
||||||
('booking', 'On Board'), ('done', 'Out'),
|
('booking', 'On Board'), ('done', 'Out'),
|
||||||
('cancelled', 'Cancelled')],
|
('cancelled', 'Cancelled')],
|
||||||
@@ -126,37 +83,27 @@ class HotelFolio(models.Model):
|
|||||||
help="Hotel services detail provide to "
|
help="Hotel services detail provide to "
|
||||||
"customer and it will include in "
|
"customer and it will include in "
|
||||||
"main Invoice.")
|
"main Invoice.")
|
||||||
# service_line_ids = fields.One2many('hotel.service.line', 'folio_id',
|
|
||||||
# readonly=False,
|
|
||||||
# states={'done': [('readonly', True)]},
|
|
||||||
# help="Hotel services detail provide to"
|
|
||||||
# "customer and it will include in "
|
|
||||||
# "main Invoice.")
|
|
||||||
# has no sense used as this way
|
|
||||||
hotel_invoice_id = fields.Many2one('account.invoice', 'Invoice')
|
hotel_invoice_id = fields.Many2one('account.invoice', 'Invoice')
|
||||||
|
|
||||||
company_id = fields.Many2one('res.company', 'Company')
|
company_id = fields.Many2one('res.company', 'Company')
|
||||||
|
|
||||||
# currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id',
|
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id',
|
||||||
# string='Currency', readonly=True, required=True)
|
string='Currency', readonly=True, required=True)
|
||||||
|
|
||||||
# pricelist_id = fields.Many2one('product.pricelist',
|
pricelist_id = fields.Many2one('product.pricelist',
|
||||||
# string='Pricelist',
|
string='Pricelist',
|
||||||
# required=True,
|
required=True,
|
||||||
# readonly=True,
|
readonly=True,
|
||||||
# states={'draft': [('readonly', False)],
|
states={'draft': [('readonly', False)],
|
||||||
# 'sent': [('readonly', False)]},
|
'sent': [('readonly', False)]},
|
||||||
# help="Pricelist for current sales order.")
|
help="Pricelist for current folio.")
|
||||||
# Monetary to Float
|
pending_amount = fields.Monetary(compute='compute_amount',
|
||||||
invoices_amount = fields.Float(compute='compute_invoices_amount',
|
|
||||||
store=True,
|
store=True,
|
||||||
string="Pending in Folio")
|
string="Pending in Folio")
|
||||||
# Monetary to Float
|
refund_amount = fields.Monetary(compute='compute_amount',
|
||||||
refund_amount = fields.Float(compute='compute_invoices_amount',
|
|
||||||
store=True,
|
store=True,
|
||||||
string="Payment Returns")
|
string="Payment Returns")
|
||||||
# Monetary to Float
|
invoices_paid = fields.Monetary(compute='compute_amount',
|
||||||
invoices_paid = fields.Float(compute='compute_invoices_amount',
|
|
||||||
store=True, track_visibility='onchange',
|
store=True, track_visibility='onchange',
|
||||||
string="Payments")
|
string="Payments")
|
||||||
|
|
||||||
@@ -228,75 +175,27 @@ class HotelFolio(models.Model):
|
|||||||
amount_total = fields.Float(string='Total', store=True, readonly=True,
|
amount_total = fields.Float(string='Total', store=True, readonly=True,
|
||||||
track_visibility='always')
|
track_visibility='always')
|
||||||
|
|
||||||
|
|
||||||
def _compute_fix_price(self):
|
|
||||||
for record in self:
|
|
||||||
for res in record.room_lines:
|
|
||||||
if res.fix_total == True:
|
|
||||||
record.fix_price = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
record.fix_price = False
|
|
||||||
|
|
||||||
def action_recalcule_payment(self):
|
|
||||||
for record in self:
|
|
||||||
for res in record.room_lines:
|
|
||||||
res.on_change_checkin_checkout_product_id()
|
|
||||||
|
|
||||||
def _computed_rooms_char(self):
|
def _computed_rooms_char(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
rooms = ', '.join(record.mapped('room_lines.room_id.name'))
|
rooms = ', '.join(record.mapped('room_lines.room_id.name'))
|
||||||
record.rooms_char = rooms
|
record.rooms_char = rooms
|
||||||
|
|
||||||
@api.model
|
|
||||||
def recompute_amount(self):
|
|
||||||
folios = self.env['hotel.folio']
|
|
||||||
if folios:
|
|
||||||
folios = folios.filtered(lambda x: (
|
|
||||||
x.name == folio_name))
|
|
||||||
folios.compute_invoices_amount()
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def _compute_num_invoices(self):
|
def _compute_num_invoices(self):
|
||||||
pass
|
pass
|
||||||
# for fol in self:
|
# for fol in self:
|
||||||
# fol.num_invoices = len(self.mapped('invoice_ids.id'))
|
# fol.num_invoices = len(self.mapped('invoice_ids.id'))
|
||||||
|
|
||||||
@api.model
|
|
||||||
def daily_plan(self):
|
|
||||||
_logger.info('daily_plan')
|
|
||||||
self._cr.execute("update hotel_folio set checkins_reservations = 0, \
|
|
||||||
checkouts_reservations = 0 where checkins_reservations > 0 \
|
|
||||||
or checkouts_reservations > 0")
|
|
||||||
folios_in = self.env['hotel.folio'].search([
|
|
||||||
('room_lines.is_checkin', '=', True)
|
|
||||||
])
|
|
||||||
folios_out = self.env['hotel.folio'].search([
|
|
||||||
('room_lines.is_checkout', '=', True)
|
|
||||||
])
|
|
||||||
for fol in folios_in:
|
|
||||||
count_checkin = fol.room_lines.search_count([
|
|
||||||
('is_checkin', '=', True), ('folio_id.id', '=', fol.id)
|
|
||||||
])
|
|
||||||
fol.write({'checkins_reservations': count_checkin})
|
|
||||||
for fol in folios_out:
|
|
||||||
count_checkout = fol.room_lines.search_count([
|
|
||||||
('is_checkout', '=', True),
|
|
||||||
('folio_id.id', '=', fol.id)
|
|
||||||
])
|
|
||||||
fol.write({'checkouts_reservations': count_checkout})
|
|
||||||
return True
|
|
||||||
|
|
||||||
# @api.depends('order_line.price_total', 'payment_ids', 'return_ids')
|
# @api.depends('order_line.price_total', 'payment_ids', 'return_ids')
|
||||||
@api.multi
|
@api.multi
|
||||||
def compute_invoices_amount(self):
|
def compute_amount(self):
|
||||||
_logger.info('compute_invoices_amount')
|
_logger.info('compute_amount')
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_pay(self):
|
def action_pay(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
partner = self.partner_id.id
|
partner = self.partner_id.id
|
||||||
amount = self.invoices_amount
|
amount = self.pending_amount
|
||||||
view_id = self.env.ref('hotel.view_account_payment_folio_form').id
|
view_id = self.env.ref('hotel.view_account_payment_folio_form').id
|
||||||
return{
|
return{
|
||||||
'name': _('Register Payment'),
|
'name': _('Register Payment'),
|
||||||
@@ -373,6 +272,178 @@ class HotelFolio(models.Model):
|
|||||||
'domain': [('id', 'in', return_move_ids)],
|
'domain': [('id', 'in', return_move_ids)],
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_folios_amount(self):
|
||||||
|
now_utc_dt = date_utils.now()
|
||||||
|
now_utc_str = now_utc_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
||||||
|
reservations = self.env['hotel.reservation'].search([
|
||||||
|
('checkout', '<=', now_utc_str)
|
||||||
|
])
|
||||||
|
folio_ids = reservations.mapped('folio_id.id')
|
||||||
|
folios = self.env['hotel.folio'].search([('id', 'in', folio_ids)])
|
||||||
|
folios = folios.filtered(lambda r: r.pending_amount > 0)
|
||||||
|
return {
|
||||||
|
'name': _('Pending'),
|
||||||
|
'view_type': 'form',
|
||||||
|
'view_mode': 'tree,form',
|
||||||
|
'res_model': 'hotel.folio',
|
||||||
|
'type': 'ir.actions.act_window',
|
||||||
|
'domain': [('id', 'in', folios.ids)]
|
||||||
|
}
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def go_to_currency_exchange(self):
|
||||||
|
'''
|
||||||
|
when Money Exchange button is clicked then this method is called.
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
@param self: object pointer
|
||||||
|
'''
|
||||||
|
_logger.info('go_to_currency_exchange')
|
||||||
|
pass
|
||||||
|
# cr, uid, context = self.env.args
|
||||||
|
# context = dict(context)
|
||||||
|
# for rec in self:
|
||||||
|
# if rec.partner_id.id and len(rec.room_lines) != 0:
|
||||||
|
# context.update({'folioid': rec.id, 'guest': rec.partner_id.id,
|
||||||
|
# 'room_no': rec.room_lines[0].product_id.name})
|
||||||
|
# self.env.args = cr, uid, misc.frozendict(context)
|
||||||
|
# else:
|
||||||
|
# raise except_orm(_('Warning'), _('Please Reserve Any Room.'))
|
||||||
|
# return {'name': _('Currency Exchange'),
|
||||||
|
# 'res_model': 'currency.exchange',
|
||||||
|
# 'type': 'ir.actions.act_window',
|
||||||
|
# 'view_id': False,
|
||||||
|
# 'view_mode': 'form,tree',
|
||||||
|
# 'view_type': 'form',
|
||||||
|
# 'context': {'default_folio_no': context.get('folioid'),
|
||||||
|
# 'default_hotel_id': context.get('hotel'),
|
||||||
|
# 'default_guest_name': context.get('guest'),
|
||||||
|
# 'default_room_number': context.get('room_no')
|
||||||
|
# },
|
||||||
|
# }
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def create(self, vals, check=True):
|
||||||
|
if vals.get('name', _('New')) == _('New'):
|
||||||
|
if 'company_id' in vals:
|
||||||
|
vals['name'] = self.env['ir.sequence'].with_context(force_company=vals['company_id']).next_by_code('sale.order') or _('New')
|
||||||
|
else:
|
||||||
|
vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio') or _('New')
|
||||||
|
|
||||||
|
# Makes sure partner_invoice_id' and 'pricelist_id' are defined
|
||||||
|
if any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id']):
|
||||||
|
partner = self.env['res.partner'].browse(vals.get('partner_id'))
|
||||||
|
addr = partner.address_get(['delivery', 'invoice'])
|
||||||
|
vals['partner_invoice_id'] = vals.setdefault('partner_invoice_id', addr['invoice'])
|
||||||
|
vals['pricelist_id'] = vals.setdefault('pricelist_id', partner.property_product_pricelist and partner.property_product_pricelist.id)
|
||||||
|
result = super(HotelFolio, self).create(vals)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
@api.onchange('partner_id')
|
||||||
|
def onchange_partner_id(self):
|
||||||
|
"""
|
||||||
|
Update the following fields when the partner is changed:
|
||||||
|
- Pricelist
|
||||||
|
- Invoice address
|
||||||
|
- user_id
|
||||||
|
"""
|
||||||
|
if not self.partner_id:
|
||||||
|
self.update({
|
||||||
|
'partner_invoice_id': False,
|
||||||
|
'payment_term_id': False,
|
||||||
|
'fiscal_position_id': False,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
|
||||||
|
addr = self.partner_id.address_get(['invoice'])
|
||||||
|
values = {
|
||||||
|
'pricelist_id': self.partner_id.property_product_pricelist and self.partner_id.property_product_pricelist.id or False,
|
||||||
|
'partner_invoice_id': addr['invoice'],
|
||||||
|
'user_id': self.partner_id.user_id.id or self.env.uid
|
||||||
|
}
|
||||||
|
if self.env['ir.config_parameter'].sudo().get_param('sale.use_sale_note') and self.env.user.company_id.sale_note:
|
||||||
|
values['note'] = self.with_context(lang=self.partner_id.lang).env.user.company_id.sale_note
|
||||||
|
|
||||||
|
if self.partner_id.team_id:
|
||||||
|
values['team_id'] = self.partner_id.team_id.id
|
||||||
|
self.update(values)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_invoice_create(self, grouped=False, states=None):
|
||||||
|
'''
|
||||||
|
@param self: object pointer
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
# if states is None:
|
||||||
|
# states = ['confirmed', 'done']
|
||||||
|
# order_ids = [folio.order_id.id for folio in self]
|
||||||
|
# sale_obj = self.env['sale.order'].browse(order_ids)
|
||||||
|
# invoice_id = (sale_obj.action_invoice_create(grouped=False,
|
||||||
|
# states=['confirmed',
|
||||||
|
# 'done']))
|
||||||
|
# for line in self:
|
||||||
|
# values = {'invoiced': True,
|
||||||
|
# 'state': 'progress' if grouped else 'progress',
|
||||||
|
# 'hotel_invoice_id': invoice_id
|
||||||
|
# }
|
||||||
|
# line.write(values)
|
||||||
|
# return invoice_id
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def advance_invoice(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
'''
|
||||||
|
WORKFLOW STATE
|
||||||
|
'''
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def button_dummy(self):
|
||||||
|
'''
|
||||||
|
@param self: object pointer
|
||||||
|
'''
|
||||||
|
# for folio in self:
|
||||||
|
# folio.order_id.button_dummy()
|
||||||
|
return True
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_done(self):
|
||||||
|
for line in self.room_lines:
|
||||||
|
if line.state == "booking":
|
||||||
|
line.action_reservation_checkout()
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_cancel(self):
|
||||||
|
'''
|
||||||
|
@param self: object pointer
|
||||||
|
'''
|
||||||
|
pass
|
||||||
|
# for sale in self:
|
||||||
|
# if not sale.order_id:
|
||||||
|
# raise ValidationError(_('Order id is not available'))
|
||||||
|
# for invoice in sale.invoice_ids:
|
||||||
|
# invoice.state = 'cancel'
|
||||||
|
# sale.room_lines.action_cancel()
|
||||||
|
# sale.order_id.action_cancel()
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def print_quotation(self):
|
||||||
|
pass
|
||||||
|
# TODO- New report to reservation order
|
||||||
|
# self.order_id.filtered(lambda s: s.state == 'draft').write({
|
||||||
|
# 'state': 'sent',
|
||||||
|
# })
|
||||||
|
# return self.env.ref('sale.report_saleorder').report_action(self, data=data)
|
||||||
|
|
||||||
|
@api.multi
|
||||||
|
def action_confirm(self):
|
||||||
|
_logger.info('action_confirm')
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
CHECKIN/OUT PROCESS
|
||||||
|
"""
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_checks(self):
|
def action_checks(self):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -386,25 +457,59 @@ class HotelFolio(models.Model):
|
|||||||
'domain': [('reservation_id', 'in', rooms)],
|
'domain': [('reservation_id', 'in', rooms)],
|
||||||
'target': 'new',
|
'target': 'new',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@api.model
|
||||||
|
def daily_plan(self):
|
||||||
|
_logger.info('daily_plan')
|
||||||
|
self._cr.execute("update hotel_folio set checkins_reservations = 0, \
|
||||||
|
checkouts_reservations = 0 where checkins_reservations > 0 \
|
||||||
|
or checkouts_reservations > 0")
|
||||||
|
folios_in = self.env['hotel.folio'].search([
|
||||||
|
('room_lines.is_checkin', '=', True)
|
||||||
|
])
|
||||||
|
folios_out = self.env['hotel.folio'].search([
|
||||||
|
('room_lines.is_checkout', '=', True)
|
||||||
|
])
|
||||||
|
for fol in folios_in:
|
||||||
|
count_checkin = fol.room_lines.search_count([
|
||||||
|
('is_checkin', '=', True), ('folio_id.id', '=', fol.id)
|
||||||
|
])
|
||||||
|
fol.write({'checkins_reservations': count_checkin})
|
||||||
|
for fol in folios_out:
|
||||||
|
count_checkout = fol.room_lines.search_count([
|
||||||
|
('is_checkout', '=', True),
|
||||||
|
('folio_id.id', '=', fol.id)
|
||||||
|
])
|
||||||
|
fol.write({'checkouts_reservations': count_checkout})
|
||||||
|
return True
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def action_folios_amount(self):
|
def _compute_cardex_count(self):
|
||||||
now_utc_dt = date_utils.now()
|
_logger.info('_compute_cardex_amount')
|
||||||
now_utc_str = now_utc_dt.strftime(DEFAULT_SERVER_DATETIME_FORMAT)
|
for fol in self:
|
||||||
reservations = self.env['hotel.reservation'].search([
|
num_cardex = 0
|
||||||
('checkout', '<=', now_utc_str)
|
pending = False
|
||||||
])
|
if fol.reservation_type == 'normal':
|
||||||
folio_ids = reservations.mapped('folio_id.id')
|
for reser in fol.room_lines:
|
||||||
folios = self.env['hotel.folio'].search([('id', 'in', folio_ids)])
|
if reser.state != 'cancelled' and \
|
||||||
folios = folios.filtered(lambda r: r.invoices_amount > 0)
|
not reser.parent_reservation:
|
||||||
return {
|
num_cardex += len(reser.cardex_ids)
|
||||||
'name': _('Pending'),
|
fol.cardex_count = num_cardex
|
||||||
'view_type': 'form',
|
pending = 0
|
||||||
'view_mode': 'tree,form',
|
for reser in fol.room_lines:
|
||||||
'res_model': 'hotel.folio',
|
if reser.state != 'cancelled' and \
|
||||||
'type': 'ir.actions.act_window',
|
not reser.parent_reservation:
|
||||||
'domain': [('id', 'in', folios.ids)]
|
pending += (reser.adults + reser.children) \
|
||||||
}
|
- len(reser.cardex_ids)
|
||||||
|
if pending <= 0:
|
||||||
|
fol.cardex_pending = False
|
||||||
|
else:
|
||||||
|
fol.cardex_pending = True
|
||||||
|
fol.cardex_pending_num = pending
|
||||||
|
|
||||||
|
"""
|
||||||
|
MAILING PROCESS
|
||||||
|
"""
|
||||||
|
|
||||||
@api.depends('room_lines')
|
@api.depends('room_lines')
|
||||||
def _compute_has_confirmed_reservations_to_send(self):
|
def _compute_has_confirmed_reservations_to_send(self):
|
||||||
@@ -468,221 +573,6 @@ class HotelFolio(models.Model):
|
|||||||
break
|
break
|
||||||
self.has_checkout_to_send = has_to_send
|
self.has_checkout_to_send = has_to_send
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def _compute_cardex_count(self):
|
|
||||||
_logger.info('_compute_cardex_amount')
|
|
||||||
for fol in self:
|
|
||||||
num_cardex = 0
|
|
||||||
pending = False
|
|
||||||
if fol.reservation_type == 'normal':
|
|
||||||
for reser in fol.room_lines:
|
|
||||||
if reser.state != 'cancelled' and \
|
|
||||||
not reser.parent_reservation:
|
|
||||||
num_cardex += len(reser.cardex_ids)
|
|
||||||
fol.cardex_count = num_cardex
|
|
||||||
pending = 0
|
|
||||||
for reser in fol.room_lines:
|
|
||||||
if reser.state != 'cancelled' and \
|
|
||||||
not reser.parent_reservation:
|
|
||||||
pending += (reser.adults + reser.children) \
|
|
||||||
- len(reser.cardex_ids)
|
|
||||||
if pending <= 0:
|
|
||||||
fol.cardex_pending = False
|
|
||||||
else:
|
|
||||||
fol.cardex_pending = True
|
|
||||||
fol.cardex_pending_num = pending
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def go_to_currency_exchange(self):
|
|
||||||
'''
|
|
||||||
when Money Exchange button is clicked then this method is called.
|
|
||||||
-------------------------------------------------------------------
|
|
||||||
@param self: object pointer
|
|
||||||
'''
|
|
||||||
_logger.info('go_to_currency_exchange')
|
|
||||||
pass
|
|
||||||
# cr, uid, context = self.env.args
|
|
||||||
# context = dict(context)
|
|
||||||
# for rec in self:
|
|
||||||
# if rec.partner_id.id and len(rec.room_lines) != 0:
|
|
||||||
# context.update({'folioid': rec.id, 'guest': rec.partner_id.id,
|
|
||||||
# 'room_no': rec.room_lines[0].product_id.name})
|
|
||||||
# self.env.args = cr, uid, misc.frozendict(context)
|
|
||||||
# else:
|
|
||||||
# raise except_orm(_('Warning'), _('Please Reserve Any Room.'))
|
|
||||||
# return {'name': _('Currency Exchange'),
|
|
||||||
# 'res_model': 'currency.exchange',
|
|
||||||
# 'type': 'ir.actions.act_window',
|
|
||||||
# 'view_id': False,
|
|
||||||
# 'view_mode': 'form,tree',
|
|
||||||
# 'view_type': 'form',
|
|
||||||
# 'context': {'default_folio_no': context.get('folioid'),
|
|
||||||
# 'default_hotel_id': context.get('hotel'),
|
|
||||||
# 'default_guest_name': context.get('guest'),
|
|
||||||
# 'default_room_number': context.get('room_no')
|
|
||||||
# },
|
|
||||||
# }
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def create(self, vals, check=True):
|
|
||||||
"""
|
|
||||||
Overrides orm create method.
|
|
||||||
@param self: The object pointer
|
|
||||||
@param vals: dictionary of fields value.
|
|
||||||
@return: new record set for hotel folio.
|
|
||||||
"""
|
|
||||||
_logger.info('create')
|
|
||||||
if not 'service_line_ids' and 'folio_id' in vals:
|
|
||||||
tmp_room_lines = vals.get('room_lines', [])
|
|
||||||
vals['order_policy'] = vals.get('hotel_policy', 'manual')
|
|
||||||
vals.update({'room_lines': []})
|
|
||||||
for line in (tmp_room_lines):
|
|
||||||
line[2].update({'folio_id': folio_id})
|
|
||||||
vals.update({'room_lines': tmp_room_lines})
|
|
||||||
folio_id = super(HotelFolio, self).create(vals)
|
|
||||||
else:
|
|
||||||
if not vals:
|
|
||||||
vals = {}
|
|
||||||
vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio')
|
|
||||||
folio_id = super(HotelFolio, self).create(vals)
|
|
||||||
|
|
||||||
return folio_id
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def write(self, vals):
|
|
||||||
if 'room_lines' in vals and vals['room_lines'][0][2] and 'reservation_line_ids' in vals['room_lines'][0][2] and vals['room_lines'][0][2]['reservation_line_ids'][0][0] == 5:
|
|
||||||
del vals['room_lines']
|
|
||||||
return super(HotelFolio, self).write(vals)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
@api.onchange('partner_id')
|
|
||||||
def onchange_partner_id(self):
|
|
||||||
'''
|
|
||||||
When you change partner_id it will update the partner_invoice_id,
|
|
||||||
partner_shipping_id and pricelist_id of the hotel folio as well
|
|
||||||
---------------------------------------------------------------
|
|
||||||
@param self: object pointer
|
|
||||||
'''
|
|
||||||
_logger.info('onchange_partner_id')
|
|
||||||
pass
|
|
||||||
# self.update({
|
|
||||||
# 'currency_id': self.env.ref('base.main_company').currency_id,
|
|
||||||
# 'partner_invoice_id': self.partner_id and self.partner_id.id or False,
|
|
||||||
# 'partner_shipping_id': self.partner_id and self.partner_id.id or False,
|
|
||||||
# 'pricelist_id': self.partner_id and self.partner_id.property_product_pricelist.id or False,
|
|
||||||
# })
|
|
||||||
# """
|
|
||||||
# Warning messajes saved in partner form to folios
|
|
||||||
# """
|
|
||||||
# if not self.partner_id:
|
|
||||||
# return
|
|
||||||
# warning = {}
|
|
||||||
# title = False
|
|
||||||
# message = False
|
|
||||||
# partner = self.partner_id
|
|
||||||
#
|
|
||||||
# # If partner has no warning, check its company
|
|
||||||
# if partner.sale_warn == 'no-message' and partner.parent_id:
|
|
||||||
# partner = partner.parent_id
|
|
||||||
#
|
|
||||||
# if partner.sale_warn != 'no-message':
|
|
||||||
# # Block if partner only has warning but parent company is blocked
|
|
||||||
# if partner.sale_warn != 'block' and partner.parent_id \
|
|
||||||
# and partner.parent_id.sale_warn == 'block':
|
|
||||||
# partner = partner.parent_id
|
|
||||||
# title = _("Warning for %s") % partner.name
|
|
||||||
# message = partner.sale_warn_msg
|
|
||||||
# warning = {
|
|
||||||
# 'title': title,
|
|
||||||
# 'message': message,
|
|
||||||
# }
|
|
||||||
# if self.partner_id.sale_warn == 'block':
|
|
||||||
# self.update({
|
|
||||||
# 'partner_id': False,
|
|
||||||
# 'partner_invoice_id': False,
|
|
||||||
# 'partner_shipping_id': False,
|
|
||||||
# 'pricelist_id': False
|
|
||||||
# })
|
|
||||||
# return {'warning': warning}
|
|
||||||
#
|
|
||||||
# if warning:
|
|
||||||
# return {'warning': warning}
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def button_dummy(self):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
'''
|
|
||||||
# for folio in self:
|
|
||||||
# folio.order_id.button_dummy()
|
|
||||||
return True
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_done(self):
|
|
||||||
for line in self.room_lines:
|
|
||||||
if line.state == "booking":
|
|
||||||
line.action_reservation_checkout()
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_invoice_create(self, grouped=False, states=None):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
# if states is None:
|
|
||||||
# states = ['confirmed', 'done']
|
|
||||||
# order_ids = [folio.order_id.id for folio in self]
|
|
||||||
# sale_obj = self.env['sale.order'].browse(order_ids)
|
|
||||||
# invoice_id = (sale_obj.action_invoice_create(grouped=False,
|
|
||||||
# states=['confirmed',
|
|
||||||
# 'done']))
|
|
||||||
# for line in self:
|
|
||||||
# values = {'invoiced': True,
|
|
||||||
# 'state': 'progress' if grouped else 'progress',
|
|
||||||
# 'hotel_invoice_id': invoice_id
|
|
||||||
# }
|
|
||||||
# line.write(values)
|
|
||||||
# return invoice_id
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def advance_invoice(self):
|
|
||||||
pass
|
|
||||||
# order_ids = [folio.order_id.id for folio in self]
|
|
||||||
# sale_obj = self.env['sale.order'].browse(order_ids)
|
|
||||||
# invoices = action_invoice_create(self, grouped=True)
|
|
||||||
# return invoices
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_cancel(self):
|
|
||||||
'''
|
|
||||||
@param self: object pointer
|
|
||||||
'''
|
|
||||||
pass
|
|
||||||
# for sale in self:
|
|
||||||
# if not sale.order_id:
|
|
||||||
# raise ValidationError(_('Order id is not available'))
|
|
||||||
# for invoice in sale.invoice_ids:
|
|
||||||
# invoice.state = 'cancel'
|
|
||||||
# sale.room_lines.action_cancel()
|
|
||||||
# sale.order_id.action_cancel()
|
|
||||||
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_confirm(self):
|
|
||||||
_logger.info('action_confirm')
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def print_quotation(self):
|
|
||||||
pass
|
|
||||||
# self.order_id.filtered(lambda s: s.state == 'draft').write({
|
|
||||||
# 'state': 'sent',
|
|
||||||
# })
|
|
||||||
# return self.env.ref('sale.report_saleorder').report_action(self, data=data)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def action_cancel_draft(self):
|
|
||||||
_logger.info('action_confirm')
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def send_reservation_mail(self):
|
def send_reservation_mail(self):
|
||||||
'''
|
'''
|
||||||
@@ -847,12 +737,6 @@ class HotelFolio(models.Model):
|
|||||||
template_rec.send_mail(reserv_rec.id, force_send=True)
|
template_rec.send_mail(reserv_rec.id, force_send=True)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def unlink(self):
|
|
||||||
# for record in self:
|
|
||||||
# record.order_id.unlink()
|
|
||||||
return super(HotelFolio, self).unlink()
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def get_grouped_reservations_json(self, state, import_all=False):
|
def get_grouped_reservations_json(self, state, import_all=False):
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
@@ -882,3 +766,4 @@ class HotelFolio(models.Model):
|
|||||||
if not founded:
|
if not founded:
|
||||||
info_grouped.append(vals)
|
info_grouped.append(vals)
|
||||||
return sorted(sorted(info_grouped, key=lambda k: k['num'], reverse=True), key=lambda k: k['room_type']['id'])
|
return sorted(sorted(info_grouped, key=lambda k: k['num'], reverse=True), key=lambda k: k['room_type']['id'])
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -20,6 +20,7 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.addons import decimal_precision as dp
|
from odoo.addons import decimal_precision as dp
|
||||||
|
from odoo.exceptions import except_orm, UserError, ValidationError
|
||||||
|
|
||||||
class HotelReservationLine(models.Model):
|
class HotelReservationLine(models.Model):
|
||||||
_name = "hotel.reservation.line"
|
_name = "hotel.reservation.line"
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
# Copyright 2017 Dario Lodeiros
|
# Copyright 2017 Dario Lodeiros
|
||||||
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
|
# 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.exceptions import ValidationError
|
||||||
|
|
||||||
class HotelRoom(models.Model):
|
class HotelRoom(models.Model):
|
||||||
""" The rooms for lodging can be for sleeping, usually called rooms, and also
|
""" The rooms for lodging can be for sleeping, usually called rooms, and also
|
||||||
@@ -11,18 +11,12 @@ class HotelRoom(models.Model):
|
|||||||
"""
|
"""
|
||||||
_name = 'hotel.room'
|
_name = 'hotel.room'
|
||||||
_description = 'Hotel Room'
|
_description = 'Hotel Room'
|
||||||
# The record's name
|
|
||||||
name = fields.Char('Room Name', required=True)
|
|
||||||
# Used for activate records
|
|
||||||
active = fields.Boolean('Active', default=True)
|
|
||||||
# Used for ordering
|
|
||||||
sequence = fields.Integer('Sequence', default=0)
|
|
||||||
|
|
||||||
_order = "sequence, room_type_id, name"
|
_order = "sequence, room_type_id, name"
|
||||||
|
|
||||||
# each room has only one type (Many2one)
|
name = fields.Char('Room Name', required=True)
|
||||||
|
active = fields.Boolean('Active', default=True)
|
||||||
|
sequence = fields.Integer('Sequence', default=0)
|
||||||
room_type_id = fields.Many2one('hotel.room.type', 'Hotel Room Type')
|
room_type_id = fields.Many2one('hotel.room.type', 'Hotel Room Type')
|
||||||
|
|
||||||
floor_id = fields.Many2one('hotel.floor', 'Ubication',
|
floor_id = fields.Many2one('hotel.floor', 'Ubication',
|
||||||
help='At which floor the room is located.')
|
help='At which floor the room is located.')
|
||||||
# TODO Q. Should the amenities be on the Room Type ? -
|
# TODO Q. Should the amenities be on the Room Type ? -
|
||||||
@@ -30,76 +24,19 @@ class HotelRoom(models.Model):
|
|||||||
'room_amenities', 'rcateg_id',
|
'room_amenities', 'rcateg_id',
|
||||||
string='Room Amenities',
|
string='Room Amenities',
|
||||||
help='List of room amenities.')
|
help='List of room amenities.')
|
||||||
|
|
||||||
# default price for this room
|
|
||||||
list_price = fields.Float(store=True,
|
|
||||||
string='Room Rate',
|
|
||||||
help='The room rate is fixed unless a room type'
|
|
||||||
' is selected, in which case the rate is taken from'
|
|
||||||
' the room type.')
|
|
||||||
# how to manage the price
|
|
||||||
# sale_price_type = fields.Selection([
|
|
||||||
# ('fixed', 'Fixed Price'),
|
|
||||||
# ('vroom', 'Room Type'),
|
|
||||||
# ], 'Price Type', default='fixed', required=True)
|
|
||||||
# max number of adults and children per room
|
|
||||||
max_adult = fields.Integer('Max Adult')
|
max_adult = fields.Integer('Max Adult')
|
||||||
max_child = fields.Integer('Max Child')
|
max_child = fields.Integer('Max Child')
|
||||||
# maximum capacity of the room
|
|
||||||
capacity = fields.Integer('Capacity')
|
capacity = fields.Integer('Capacity')
|
||||||
# FIXME not used
|
# FIXME not used
|
||||||
to_be_cleaned = fields.Boolean('To be Cleaned', default=False)
|
to_be_cleaned = fields.Boolean('To be Cleaned', default=False)
|
||||||
|
|
||||||
shared_room = fields.Boolean('Shared Room', default=False)
|
shared_room = fields.Boolean('Shared Room', default=False)
|
||||||
|
|
||||||
description_sale = fields.Text(
|
description_sale = fields.Text(
|
||||||
'Sale Description', translate=True,
|
'Sale Description', translate=True,
|
||||||
help="A description of the Product that you want to communicate to "
|
help="A description of the Product that you want to communicate to "
|
||||||
" your customers. This description will be copied to every Sales "
|
" your customers. This description will be copied to every Sales "
|
||||||
" Order, Delivery Order and Customer Invoice/Credit Note")
|
" Order, Delivery Order and Customer Invoice/Credit Note")
|
||||||
|
|
||||||
|
@api.constrains('capacity')
|
||||||
# In case the price is managed from a specific type of room
|
def _check_capacity(self):
|
||||||
# price_virtual_room = fields.Many2one(
|
if self.capacity < 1:
|
||||||
# 'hotel.virtual.room',
|
raise ValidationError(_("Room capacity can't be less than one"))
|
||||||
# 'Price Virtual Room',
|
|
||||||
# help='Price will be based on selected Virtual Room')
|
|
||||||
|
|
||||||
# virtual_rooms = fields.Many2many('hotel.virtual.room',
|
|
||||||
# string='Virtual Rooms')
|
|
||||||
# categ_id = fields.Selection([('room', 'Room '),
|
|
||||||
# ('shared_room', 'Shared Room'),
|
|
||||||
# ('parking', 'Parking')],
|
|
||||||
# string='Hotel Lodging Type',
|
|
||||||
# store=True, default='room')
|
|
||||||
|
|
||||||
# price_virtual_room_domain = fields.Char(
|
|
||||||
# compute=_compute_price_virtual_room_domain,
|
|
||||||
# readonly=True,
|
|
||||||
# store=False,
|
|
||||||
# )
|
|
||||||
|
|
||||||
# @api.multi
|
|
||||||
# @api.depends('categ_id')
|
|
||||||
# def _compute_price_virtual_room_domain(self):
|
|
||||||
# for rec in self:
|
|
||||||
# rec.price_virtual_room_domain = json.dumps(
|
|
||||||
# ['|', ('room_ids.id', '=', rec.id), ('room_type_ids.cat_id.id', '=', rec.categ_id.id)]
|
|
||||||
# )
|
|
||||||
|
|
||||||
# @api.onchange('categ_id')
|
|
||||||
# def price_virtual_room_domain(self):
|
|
||||||
# return {
|
|
||||||
# 'domain': {
|
|
||||||
# 'price_virtual_room': [
|
|
||||||
# '|', ('room_ids.id', '=', self._origin.id),
|
|
||||||
# ('room_type_ids.cat_id.id', '=', self.categ_id.id)
|
|
||||||
# ]
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
|
|
||||||
# @api.multi
|
|
||||||
# def unlink(self):
|
|
||||||
# for record in self:
|
|
||||||
# record.product_id.unlink()
|
|
||||||
# return super(HotelRoom, self).unlink()
|
|
||||||
|
|||||||
@@ -16,8 +16,6 @@ from odoo.tools import (
|
|||||||
from odoo import models, fields, api, _
|
from odoo import models, fields, api, _
|
||||||
from odoo.addons.hotel import date_utils
|
from odoo.addons.hotel import date_utils
|
||||||
|
|
||||||
from odoo.addons import decimal_precision as dp
|
|
||||||
|
|
||||||
class HotelRoomType(models.Model):
|
class HotelRoomType(models.Model):
|
||||||
""" Before creating a 'room type', you need to consider the following:
|
""" Before creating a 'room type', you need to consider the following:
|
||||||
With the term 'room type' is meant a type of residential accommodation: for
|
With the term 'room type' is meant a type of residential accommodation: for
|
||||||
@@ -31,8 +29,6 @@ class HotelRoomType(models.Model):
|
|||||||
product_id = fields.Many2one('product.product', 'Product Room Type',
|
product_id = fields.Many2one('product.product', 'Product Room Type',
|
||||||
required=True, delegate=True,
|
required=True, delegate=True,
|
||||||
ondelete='cascade')
|
ondelete='cascade')
|
||||||
# cat_id = fields.Many2one('product.category', 'category', required=True,
|
|
||||||
# delegate=True, index=True, ondelete='cascade')
|
|
||||||
room_ids = fields.One2many('hotel.room', 'room_type_id', 'Rooms')
|
room_ids = fields.One2many('hotel.room', 'room_type_id', 'Rooms')
|
||||||
|
|
||||||
# TODO Hierarchical relationship for parent-child tree ?
|
# TODO Hierarchical relationship for parent-child tree ?
|
||||||
@@ -53,68 +49,51 @@ class HotelRoomType(models.Model):
|
|||||||
'code must be unique!')]
|
'code must be unique!')]
|
||||||
# total number of rooms in this type
|
# total number of rooms in this type
|
||||||
total_rooms_count = fields.Integer(compute='_compute_total_rooms')
|
total_rooms_count = fields.Integer(compute='_compute_total_rooms')
|
||||||
# FIXING rename to default rooms ?
|
|
||||||
max_real_rooms = fields.Integer('Default Max Room Allowed')
|
|
||||||
|
|
||||||
@api.depends('room_ids')
|
@api.depends('room_ids')
|
||||||
def _compute_total_rooms(self):
|
def _compute_total_rooms(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
count = 0
|
record.total_rooms_count = len(record.room_ids)
|
||||||
count += len(record.room_ids) # Rooms linked directly
|
|
||||||
# room_categories = r.room_type_ids.mapped('room_ids.id')
|
|
||||||
# count += self.env['hotel.room'].search_count([
|
|
||||||
# ('categ_id.id', 'in', room_categories)
|
|
||||||
# ]) # Rooms linked through room type
|
|
||||||
record.total_rooms_count = count
|
|
||||||
|
|
||||||
def _check_duplicated_rooms(self):
|
def _check_duplicated_rooms(self):
|
||||||
# FIXME Using a Many2one relationship duplicated should not been possible
|
# FIXME Using a Many2one relationship duplicated should not been possible
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@api.constrains('max_real_rooms', 'room_ids')
|
|
||||||
def _check_max_rooms(self):
|
|
||||||
warning_msg = ""
|
|
||||||
# for r in self:
|
|
||||||
if self.max_real_rooms > self.total_rooms_count:
|
|
||||||
warning_msg += _('The Maxime rooms allowed can not be greate \
|
|
||||||
than total rooms count')
|
|
||||||
raise models.ValidationError(warning_msg)
|
|
||||||
|
|
||||||
@api.multi
|
@api.multi
|
||||||
def get_capacity(self):
|
def get_capacity(self):
|
||||||
# WARNING use selg.capacity directly ?
|
"""
|
||||||
pass
|
Get the minimum capacity in the rooms of this type or zero if has no rooms
|
||||||
# self.ensure_one()
|
@param self: The object pointer
|
||||||
# hotel_room_obj = self.env['hotel.room']
|
@return: An integer with the capacity of this room type
|
||||||
# room_categories = self.room_type_ids.mapped('room_ids.id')
|
"""
|
||||||
# room_ids = self.room_ids + hotel_room_obj.search([
|
self.ensure_one()
|
||||||
# ('categ_id.id', 'in', room_categories)
|
capacities = self.room_ids.mapped('capacity')
|
||||||
# ])
|
return any(capacities) and min(capacities) or 0
|
||||||
# capacities = room_ids.mapped('capacity')
|
|
||||||
# return any(capacities) and min(capacities) or 0
|
|
||||||
|
|
||||||
@api.model
|
@api.model
|
||||||
def check_availability_virtual_room(self, checkin, checkout,
|
# TODO Rename to check_availability_room_type
|
||||||
|
def check_availability_virtual_room(self, dfrom, dto,
|
||||||
room_type_id=False, notthis=[]):
|
room_type_id=False, notthis=[]):
|
||||||
"""
|
"""
|
||||||
Check the avalability for an specific type of room
|
Check the avalability for an specific type of room
|
||||||
|
@param self: The object pointer
|
||||||
|
@param dfrom: Range date from
|
||||||
|
@param dto: Range date to
|
||||||
|
@param room_type_id: Room Type
|
||||||
|
@param notthis: Array excluding Room Types
|
||||||
@return: A recordset of free rooms ?
|
@return: A recordset of free rooms ?
|
||||||
"""
|
"""
|
||||||
occupied = self.env['hotel.reservation'].occupied(checkin, checkout)
|
reservations = self.env['hotel.reservation'].get_reservations(dfrom, dto)
|
||||||
rooms_occupied = occupied.mapped('product_id.id')
|
reservations_rooms = reservations.mapped('room_id.id')
|
||||||
free_rooms = self.env['hotel.room'].search([
|
free_rooms = self.env['hotel.room'].search([
|
||||||
('product_id.id', 'not in', rooms_occupied),
|
('id', 'not in', reservations_rooms),
|
||||||
('id', 'not in', notthis)
|
('id', 'not in', notthis)
|
||||||
])
|
])
|
||||||
if room_type_id:
|
if room_type_id:
|
||||||
# hotel_room_obj = self.env['hotel.room']
|
|
||||||
room_type_id = self.env['hotel.room.type'].search([
|
room_type_id = self.env['hotel.room.type'].search([
|
||||||
('id', '=', room_type_id)
|
('id', '=', room_type_id)
|
||||||
])
|
])
|
||||||
# room_categories = virtual_room.room_type_ids.mapped('room_ids.id')
|
# QUESTION What linked represent? Rooms in this type ?
|
||||||
# rooms_linked = virtual_room.room_ids | hotel_room_obj.search([
|
|
||||||
# ('categ_id.id', 'in', room_categories)])
|
|
||||||
# rooms_linked = room_type_id.room_ids
|
|
||||||
rooms_linked = self.room_ids
|
rooms_linked = self.room_ids
|
||||||
free_rooms = free_rooms & rooms_linked
|
free_rooms = free_rooms & rooms_linked
|
||||||
return free_rooms.sorted(key=lambda r: r.sequence)
|
return free_rooms.sorted(key=lambda r: r.sequence)
|
||||||
@@ -135,7 +114,5 @@ class HotelRoomType(models.Model):
|
|||||||
@api.multi
|
@api.multi
|
||||||
def unlink(self):
|
def unlink(self):
|
||||||
for record in self:
|
for record in self:
|
||||||
# Set fixed price to rooms with price from this virtual rooms
|
|
||||||
# Remove product.product
|
|
||||||
record.product_id.unlink()
|
record.product_id.unlink()
|
||||||
return super().unlink()
|
return super().unlink()
|
||||||
|
|||||||
@@ -90,5 +90,5 @@ class AccountPayment(models.Model):
|
|||||||
raise except_orm(_('Warning'), _('This pay is related with \
|
raise except_orm(_('Warning'), _('This pay is related with \
|
||||||
more than one Reservation.'))
|
more than one Reservation.'))
|
||||||
else:
|
else:
|
||||||
fol.compute_invoices_amount()
|
fol.compute_amount()
|
||||||
return res
|
return res
|
||||||
|
|||||||
@@ -36,4 +36,4 @@ class PaymentReturn(models.Model):
|
|||||||
payments = self.env['account.payment'].search([('move_line_ids','in',line.move_line_ids.ids)])
|
payments = self.env['account.payment'].search([('move_line_ids','in',line.move_line_ids.ids)])
|
||||||
folio_ids += payments.mapped('folio_id.id')
|
folio_ids += payments.mapped('folio_id.id')
|
||||||
folios = self.env['hotel.folio'].browse(folio_ids)
|
folios = self.env['hotel.folio'].browse(folio_ids)
|
||||||
folios.compute_invoices_amount()
|
folios.compute_amount()
|
||||||
|
|||||||
@@ -1,137 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2017 Solucións Aloxa S.L. <info@aloxa.eu>
|
|
||||||
# Dario Lodeiros <>
|
|
||||||
# Alexandre Díaz <dev@redneboa.es>
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation, either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
from decimal import Decimal
|
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import dateutil.parser
|
|
||||||
# For Python 3.0 and later
|
|
||||||
from urllib.request import urlopen
|
|
||||||
import time
|
|
||||||
from openerp.exceptions import except_orm, UserError, ValidationError
|
|
||||||
from openerp.tools import (
|
|
||||||
misc,
|
|
||||||
DEFAULT_SERVER_DATE_FORMAT,
|
|
||||||
DEFAULT_SERVER_DATETIME_FORMAT)
|
|
||||||
from openerp import models, fields, api, _
|
|
||||||
from odoo.addons.hotel import date_utils
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualRoom(models.Model):
|
|
||||||
_name = 'hotel.virtual.room'
|
|
||||||
_inherits = {'product.product': 'product_id'}
|
|
||||||
|
|
||||||
@api.depends('room_ids', 'room_type_ids')
|
|
||||||
def _compute_total_rooms(self):
|
|
||||||
for r in self:
|
|
||||||
count = 0
|
|
||||||
count += len(r.room_ids) # Rooms linked directly
|
|
||||||
room_categories = r.room_type_ids.mapped('room_ids.id')
|
|
||||||
count += self.env['hotel.room'].search_count([
|
|
||||||
('categ_id.id', 'in', room_categories)
|
|
||||||
]) # Rooms linked through room type
|
|
||||||
r.total_rooms_count = count
|
|
||||||
|
|
||||||
@api.constrains('room_ids', 'room_type_ids')
|
|
||||||
def _check_duplicated_rooms(self):
|
|
||||||
warning_msg = ""
|
|
||||||
for r in self:
|
|
||||||
room_categories = self.room_type_ids.mapped('room_ids.id')
|
|
||||||
if self.room_ids & self.env['hotel.room'].search([
|
|
||||||
('categ_id.id', 'in', room_categories)]):
|
|
||||||
room_ids = self.room_ids & self.env['hotel.room'].search([
|
|
||||||
('categ_id.id', 'in', room_categories)
|
|
||||||
])
|
|
||||||
rooms_name = ','.join(str(x.name) for x in room_ids)
|
|
||||||
warning_msg += _('You can not enter the same room in duplicate \
|
|
||||||
(check the room types) %s') % rooms_name
|
|
||||||
raise models.ValidationError(warning_msg)
|
|
||||||
|
|
||||||
@api.constrains('max_real_rooms', 'room_ids', 'room_type_ids')
|
|
||||||
def _check_max_rooms(self):
|
|
||||||
warning_msg = ""
|
|
||||||
for r in self:
|
|
||||||
if self.max_real_rooms > self.total_rooms_count:
|
|
||||||
warning_msg += _('The Maxime rooms allowed can not be greate \
|
|
||||||
than total rooms count')
|
|
||||||
raise models.ValidationError(warning_msg)
|
|
||||||
|
|
||||||
virtual_code = fields.Char('Code') # not used
|
|
||||||
room_ids = fields.Many2many('hotel.room', string='Rooms')
|
|
||||||
room_type_ids = fields.Many2many('hotel.room.type', string='Room Types')
|
|
||||||
total_rooms_count = fields.Integer(compute='_compute_total_rooms')
|
|
||||||
product_id = fields.Many2one('product.product', 'Product_id',
|
|
||||||
required=True, delegate=True,
|
|
||||||
ondelete='cascade')
|
|
||||||
# FIXME services are related to real rooms
|
|
||||||
service_ids = fields.Many2many('hotel.services',
|
|
||||||
string='Included Services')
|
|
||||||
max_real_rooms = fields.Integer('Default Max Room Allowed')
|
|
||||||
product_id = fields.Many2one(
|
|
||||||
'product.product', required=True,
|
|
||||||
ondelete='cascade')
|
|
||||||
active = fields.Boolean(default=True, help="The active field allows you to hide the category without removing it.")
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def get_capacity(self):
|
|
||||||
self.ensure_one()
|
|
||||||
hotel_room_obj = self.env['hotel.room']
|
|
||||||
room_categories = self.room_type_ids.mapped('room_ids.id')
|
|
||||||
room_ids = self.room_ids + hotel_room_obj.search([
|
|
||||||
('categ_id.id', 'in', room_categories)
|
|
||||||
])
|
|
||||||
capacities = room_ids.mapped('capacity')
|
|
||||||
return any(capacities) and min(capacities) or 0
|
|
||||||
|
|
||||||
@api.model
|
|
||||||
def check_availability_virtual_room(self, checkin, checkout,
|
|
||||||
virtual_room_id=False, notthis=[]):
|
|
||||||
occupied = self.env['hotel.reservation'].occupied(checkin, checkout)
|
|
||||||
rooms_occupied = occupied.mapped('product_id.id')
|
|
||||||
free_rooms = self.env['hotel.room'].search([
|
|
||||||
('product_id.id', 'not in', rooms_occupied),
|
|
||||||
('id', 'not in', notthis)
|
|
||||||
])
|
|
||||||
if virtual_room_id:
|
|
||||||
hotel_room_obj = self.env['hotel.room']
|
|
||||||
virtual_room = self.env['hotel.virtual.room'].search([
|
|
||||||
('id', '=', virtual_room_id)
|
|
||||||
])
|
|
||||||
room_categories = virtual_room.room_type_ids.mapped('room_ids.id')
|
|
||||||
rooms_linked = virtual_room.room_ids | hotel_room_obj.search([
|
|
||||||
('categ_id.id', 'in', room_categories)])
|
|
||||||
free_rooms = free_rooms & rooms_linked
|
|
||||||
return free_rooms.sorted(key=lambda r: r.sequence)
|
|
||||||
|
|
||||||
@api.multi
|
|
||||||
def unlink(self):
|
|
||||||
for record in self:
|
|
||||||
# Set fixed price to rooms with price from this virtual rooms
|
|
||||||
rooms = self.env['hotel.room'].search([
|
|
||||||
('sale_price_type', '=', 'vroom'),
|
|
||||||
('price_virtual_room', '=', record.id)
|
|
||||||
])
|
|
||||||
for room in rooms:
|
|
||||||
room.sale_price_type = 'fixed'
|
|
||||||
# Remove product.product
|
|
||||||
record.product_id.unlink()
|
|
||||||
return super(VirtualRoom, self).unlink()
|
|
||||||
@@ -84,10 +84,10 @@
|
|||||||
id="payment_smart_button"
|
id="payment_smart_button"
|
||||||
icon="fa-money"
|
icon="fa-money"
|
||||||
name="action_pay"
|
name="action_pay"
|
||||||
attrs="{'invisible': ['|',('invoices_amount','<=',0)]}">
|
attrs="{'invisible': ['|',('pending_amount','<=',0)]}">
|
||||||
<div class="o_form_field o_stat_info">
|
<div class="o_form_field o_stat_info">
|
||||||
<span class="o_stat_value">
|
<span class="o_stat_value">
|
||||||
<field name="invoices_amount" nolabel="1"
|
<field name="pending_amount" nolabel="1"
|
||||||
widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
widget="monetary" options="{'currency_field': 'currency_id'}"/>
|
||||||
</span>
|
</span>
|
||||||
<span class="o_stat_text">Pending Payment</span>
|
<span class="o_stat_text">Pending Payment</span>
|
||||||
@@ -221,8 +221,8 @@
|
|||||||
<!-- <field name="customer_lead" invisible="1"/> -->
|
<!-- <field name="customer_lead" invisible="1"/> -->
|
||||||
<!-- <field name="currency_id" invisible="1"/> -->
|
<!-- <field name="currency_id" invisible="1"/> -->
|
||||||
<!-- <field name="price_unit" invisible="1"/> -->
|
<!-- <field name="price_unit" invisible="1"/> -->
|
||||||
<field name="amount_room" string="Reservation Price" readonly="1"/>
|
<!-- <field name="amount_room" string="Reservation Price" readonly="1"/>-->
|
||||||
<field name="amount_discount" string="Final Price"/>
|
<!-- <field name="amount_discount" string="Final Price"/> -->
|
||||||
<button type="object" class="oe_stat_button"
|
<button type="object" class="oe_stat_button"
|
||||||
id="go_reservation" icon="fa fa-2x fa-bars"
|
id="go_reservation" icon="fa fa-2x fa-bars"
|
||||||
name="open_reservation_form"/>
|
name="open_reservation_form"/>
|
||||||
@@ -277,6 +277,16 @@
|
|||||||
</header>
|
</header>
|
||||||
<span class="label label-danger" attrs="{'invisible': [('state', 'not in', ('cancelled'))]}">Cancelled Reservation!</span>
|
<span class="label label-danger" attrs="{'invisible': [('state', 'not in', ('cancelled'))]}">Cancelled Reservation!</span>
|
||||||
<span class="label label-warning" attrs="{'invisible': [('overbooking', '=', False)]}">OverBooking!</span>
|
<span class="label label-warning" attrs="{'invisible': [('overbooking', '=', False)]}">OverBooking!</span>
|
||||||
|
<h1>
|
||||||
|
<field name="room_id" select="1"
|
||||||
|
nolabel="1" options="{'no_create': True,'no_open': True}" placeholder="Room"
|
||||||
|
style="margin-right: 30px;" required='1'/>
|
||||||
|
<field name="partner_id" default_focus="1"
|
||||||
|
placeholder="Lastname, Firstname"
|
||||||
|
attrs="{'readonly':[('folio_id','!=',False)]}"
|
||||||
|
required="1"/>
|
||||||
|
<span class="fa fa-user" style="margin-left:20px;"/>
|
||||||
|
</h1>
|
||||||
<h3>
|
<h3>
|
||||||
<!-- <field name="room_id" select="1" domain="[('isroom','=',True)]"
|
<!-- <field name="room_id" select="1" domain="[('isroom','=',True)]"
|
||||||
nolabel="1" options="{'no_create': True,'no_open': True}" placeholder="Room"
|
nolabel="1" options="{'no_create': True,'no_open': True}" placeholder="Room"
|
||||||
@@ -304,17 +314,17 @@
|
|||||||
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts">
|
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts">
|
||||||
<!-- <field name="amount_room" widget="monetary" options="{'currency_field': 'currency_id'}"/> -->
|
<!-- <field name="amount_room" widget="monetary" options="{'currency_field': 'currency_id'}"/> -->
|
||||||
<!-- <field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" /> -->
|
<!-- <field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" /> -->
|
||||||
<field name="discount_fixed" string="Room Discount" attrs="{'invisible': [('discount_type','=','percent')]}" />
|
<!-- <field name="discount_fixed" string="Room Discount" attrs="{'invisible': [('discount_type','=','percent')]}" />
|
||||||
<field name="discount_type" widget="radio" options="{'horizontal': true}" nolabel="1" colspan="2"/>
|
<field name="discount_type" widget="radio" options="{'horizontal': true}" nolabel="1" colspan="2"/>
|
||||||
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
||||||
<label for="amount_discount" />
|
<label for="amount_discount" />
|
||||||
<button name="%(action_hotel_massive_price_change_reservation_days)d" string="Massive Day Prices"
|
<button name="%(action_hotel_massive_price_change_reservation_days)d" string="Massive Day Prices"
|
||||||
type="action" class="oe_edit_only oe_link" icon="fa-bolt"/>
|
type="action" class="oe_edit_only oe_link" icon="fa-bolt"/>
|
||||||
</div>
|
</div>-->
|
||||||
<!-- <field name="amount_discount" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
<!-- <field name="amount_discount" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
||||||
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
<!--<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
||||||
<label for="amount_reservation_services" />
|
<label for="amount_reservation_services" />
|
||||||
</div>
|
</div>-->
|
||||||
<!-- <field name="amount_reservation_services" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
<!-- <field name="amount_reservation_services" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
||||||
<field name="price_total" invisible="1"/>
|
<field name="price_total" invisible="1"/>
|
||||||
<!-- <field name="qty_delivered_updateable" invisible="1"/> -->
|
<!-- <field name="qty_delivered_updateable" invisible="1"/> -->
|
||||||
@@ -509,7 +519,7 @@
|
|||||||
<field name="partner_id"/>
|
<field name="partner_id"/>
|
||||||
<field name="room_lines"/>
|
<field name="room_lines"/>
|
||||||
<field name="service_line_ids"/>
|
<field name="service_line_ids"/>
|
||||||
<field name="invoices_amount"/>
|
<field name="pending_amount"/>
|
||||||
<field name="refund_amount"/>
|
<field name="refund_amount"/>
|
||||||
<field name="invoices_paid"/>
|
<field name="invoices_paid"/>
|
||||||
<field name="booking_pending"/>
|
<field name="booking_pending"/>
|
||||||
|
|||||||
@@ -181,6 +181,8 @@
|
|||||||
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancelled'))]}"/>
|
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancelled'))]}"/>
|
||||||
</group>
|
</group>
|
||||||
<group colspan="4" string="Reservation Details" name="reservation_details">
|
<group colspan="4" string="Reservation Details" name="reservation_details">
|
||||||
|
<field name="arrival_hour"/>
|
||||||
|
<field name="departure_hour"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="adults"/>
|
<field name="adults"/>
|
||||||
<field name="children"/>
|
<field name="children"/>
|
||||||
@@ -191,30 +193,30 @@
|
|||||||
<field name="channel_type" attrs="{'required':[('reservation_type','not in',('staff','out'))]}"/>
|
<field name="channel_type" attrs="{'required':[('reservation_type','not in',('staff','out'))]}"/>
|
||||||
</group>
|
</group>
|
||||||
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts" attrs="{'invisible':[('folio_id','=', False)]}">
|
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts" attrs="{'invisible':[('folio_id','=', False)]}">
|
||||||
<!-- <field name="amount_room" widget="monetary" options="{'currency_field': 'currency_id'}"/> -->
|
<!--
|
||||||
<!-- <field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" /> -->
|
<field name="discount" string="Room Discount" attrs="{'invisible': [('discount_type','=','fixed')]}" />
|
||||||
<field name="discount_fixed" string="Room Discount" attrs="{'invisible': [('discount_type','=','percent')]}" />
|
-->
|
||||||
<field name="discount_type" widget="radio" options="{'horizontal': true}" nolabel="1" colspan="2"/>
|
|
||||||
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
||||||
|
<!--
|
||||||
<label for="amount_discount" />
|
<label for="amount_discount" />
|
||||||
|
-->
|
||||||
<button name="%(action_hotel_massive_price_change_reservation_days)d" string="Massive Day Prices"
|
<button name="%(action_hotel_massive_price_change_reservation_days)d" string="Massive Day Prices"
|
||||||
type="action" class="oe_edit_only oe_link" icon="fa-bolt"/>
|
type="action" class="oe_edit_only oe_link" icon="fa-bolt"/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <field name="amount_discount" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
<!-- <field name="amount_discount" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
||||||
|
<!--
|
||||||
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
|
||||||
<label for="amount_reservation_services" />
|
<label for="amount_reservation_services" />
|
||||||
</div>
|
</div>
|
||||||
|
-->
|
||||||
<!-- <field name="amount_reservation_services" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
<!-- <field name="amount_reservation_services" nolabel="1" widget='monetary' class="oe_subtotal_footer_separator" options="{'currency_field': 'currency_id'}"/> -->
|
||||||
<field name="price_total" invisible="1"/>
|
<field name="price_total" />
|
||||||
<!-- <field name="qty_delivered_updateable" invisible="1"/> -->
|
<!-- <field name="qty_delivered_updateable" invisible="1"/> -->
|
||||||
<field name="state" invisible="1"/>
|
<field name="state" invisible="1"/>
|
||||||
<!-- <field name="invoice_status" invisible="1"/> -->
|
<!-- <field name="invoice_status" invisible="1"/> -->
|
||||||
<!-- <field name="customer_lead" invisible="1"/> -->
|
<!-- <field name="customer_lead" invisible="1"/> -->
|
||||||
<!-- <field name="currency_id" invisible="1"/> -->
|
<field name="currency_id" invisible="1"/>
|
||||||
<field name="price_subtotal" widget="monetary" invisible="1"/>
|
<field name="price_subtotal" widget="monetary"/>
|
||||||
<!-- <field name="price_unit" invisible="1"/> -->
|
|
||||||
<!-- <field name="fix_total" invisible="1" /> -->
|
|
||||||
<!-- <field name="fix_folio_pending" invisible="1" /> -->
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<field name="folio_internal_comment" nolabel="1" placeholder="Reservation Notes"/>
|
<field name="folio_internal_comment" nolabel="1" placeholder="Reservation Notes"/>
|
||||||
@@ -263,7 +265,7 @@
|
|||||||
<group colspan="4" string="Days" name="days">
|
<group colspan="4" string="Days" name="days">
|
||||||
<field name="reservation_line_ids" nolabel="1">
|
<field name="reservation_line_ids" nolabel="1">
|
||||||
<tree create="false" delete="false" editable="bottom">
|
<tree create="false" delete="false" editable="bottom">
|
||||||
<field name="date" readonly="True" />
|
<field name="date" />
|
||||||
<field name="price" />
|
<field name="price" />
|
||||||
<field name="discount" />
|
<field name="discount" />
|
||||||
</tree>
|
</tree>
|
||||||
@@ -413,10 +415,10 @@
|
|||||||
/>
|
/>
|
||||||
<separator/>
|
<separator/>
|
||||||
<filter string="Still to be paid"
|
<filter string="Still to be paid"
|
||||||
domain="[('folio_id.invoices_amount','>',0)]"
|
domain="[('folio_id.pending_amount','>',0)]"
|
||||||
/>
|
/>
|
||||||
<filter string="Late Payment"
|
<filter string="Late Payment"
|
||||||
domain="[('folio_id.invoices_amount','>',0),('state','in',['done'])]"
|
domain="[('folio_id.pending_amount','>',0),('state','in',['done'])]"
|
||||||
/>
|
/>
|
||||||
<filter string="Lates and NoShows"
|
<filter string="Lates and NoShows"
|
||||||
domain="[('cancelled_reason','in',['late','noshow'])]"
|
domain="[('cancelled_reason','in',['late','noshow'])]"
|
||||||
|
|||||||
@@ -41,7 +41,6 @@
|
|||||||
<!--field name="price_virtual_room_domain" invisible="1" /-->
|
<!--field name="price_virtual_room_domain" invisible="1" /-->
|
||||||
<!-- <field name="price_virtual_room" domain="[('room_ids.id', '=', active_id)]" attrs="{'invisible':[('sale_price_type', '!=', 'vroom')], 'required': [('sale_price_type', '=', 'vroom')]}" /> -->
|
<!-- <field name="price_virtual_room" domain="[('room_ids.id', '=', active_id)]" attrs="{'invisible':[('sale_price_type', '!=', 'vroom')], 'required': [('sale_price_type', '=', 'vroom')]}" /> -->
|
||||||
<!-- <field name="price_room_type" domain="[('room_ids.id', '=', active_id)]" attrs="{'invisible':[('sale_price_type', '!=', 'vroom')], 'required': [('sale_price_type', '=', 'vroom')]}" /> -->
|
<!-- <field name="price_room_type" domain="[('room_ids.id', '=', active_id)]" attrs="{'invisible':[('sale_price_type', '!=', 'vroom')], 'required': [('sale_price_type', '=', 'vroom')]}" /> -->
|
||||||
<field name="list_price" />
|
|
||||||
</group>
|
</group>
|
||||||
<newline />
|
<newline />
|
||||||
<!-- <separator colspan='4' string="Customer Taxes" /> -->
|
<!-- <separator colspan='4' string="Customer Taxes" /> -->
|
||||||
@@ -75,7 +74,6 @@
|
|||||||
<search string="Hotel Room">
|
<search string="Hotel Room">
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="room_type_id" />
|
<field name="room_type_id" />
|
||||||
<field name="list_price" string="Room rate" />
|
|
||||||
<field name="capacity" />
|
<field name="capacity" />
|
||||||
<newline />
|
<newline />
|
||||||
<!--<filter name="available" string="Available"
|
<!--<filter name="available" string="Available"
|
||||||
@@ -95,7 +93,6 @@
|
|||||||
<field name="sequence" widget="handle"/>
|
<field name="sequence" widget="handle"/>
|
||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="room_type_id" />
|
<field name="room_type_id" />
|
||||||
<field name="list_price" string="Room rate" />
|
|
||||||
<field name="capacity" />
|
<field name="capacity" />
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
|
|||||||
@@ -20,23 +20,15 @@
|
|||||||
<field name="name" />
|
<field name="name" />
|
||||||
<field name="code_type" />
|
<field name="code_type" />
|
||||||
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}"/>
|
<field name="list_price" widget='monetary' options="{'currency_field': 'currency_id', 'field_digits': True}"/>
|
||||||
<!-- <field name="parent_id" domain="[('isroomtype','=',True)]"
|
|
||||||
select="1" />
|
|
||||||
<field name="isroomtype" invisible="1" /> -->
|
|
||||||
</group>
|
</group>
|
||||||
<group>
|
<group>
|
||||||
<field name="total_rooms_count"/>
|
<field name="total_rooms_count"/>
|
||||||
<field name="max_real_rooms"/>
|
|
||||||
<!-- <field name="room_type_ids" widget="many2many_tags" options="{'no_create': True}"/> -->
|
|
||||||
</group>
|
</group>
|
||||||
</group>
|
</group>
|
||||||
<group colspan="2">
|
<group colspan="2">
|
||||||
<group>
|
<group>
|
||||||
<field name="room_ids" widget="many2many"/>
|
<field name="room_ids" widget="many2many"/>
|
||||||
</group>
|
</group>
|
||||||
<!-- <group>
|
|
||||||
<field name="service_ids"/>
|
|
||||||
</group> -->
|
|
||||||
</group>
|
</group>
|
||||||
</sheet>
|
</sheet>
|
||||||
</form>
|
</form>
|
||||||
@@ -55,7 +47,6 @@
|
|||||||
<field name="list_price"/>
|
<field name="list_price"/>
|
||||||
<field name="room_ids"/>
|
<field name="room_ids"/>
|
||||||
<field name="total_rooms_count"/>
|
<field name="total_rooms_count"/>
|
||||||
<field name="max_real_rooms"/>
|
|
||||||
</tree>
|
</tree>
|
||||||
</field>
|
</field>
|
||||||
</record>
|
</record>
|
||||||
@@ -65,7 +56,6 @@
|
|||||||
<field name="name">Room Type</field>
|
<field name="name">Room Type</field>
|
||||||
<field name="res_model">hotel.room.type</field>
|
<field name="res_model">hotel.room.type</field>
|
||||||
<field name="view_type">form</field>
|
<field name="view_type">form</field>
|
||||||
<!-- <field name="context">{'default_isroomtype':1}</field> -->
|
|
||||||
<field name="view_mode">tree,form</field>
|
<field name="view_mode">tree,form</field>
|
||||||
</record>
|
</record>
|
||||||
<menuitem id="menu_hotel_room" name="Room"
|
<menuitem id="menu_hotel_room" name="Room"
|
||||||
|
|||||||
Reference in New Issue
Block a user