Merge pull request #77 from hootel/pr_price_compute

Pr price compute
This commit is contained in:
Darío Lodeiros
2018-12-18 19:35:59 +01:00
committed by GitHub
7 changed files with 285 additions and 171 deletions

View File

@@ -46,6 +46,7 @@
'views/hotel_room_type_restriction_item_views.xml',
'views/hotel_reservation_views.xml',
'views/hotel_room_closure_reason_views.xml',
'views/hotel_service_views.xml',
'views/hotel_board_service_views.xml',
'views/hotel_checkin_partner_views.xml',
'views/hotel_room_type_availability_views.xml',

View File

@@ -44,30 +44,11 @@ class HotelFolio(models.Model):
def _amount_all(self):
pass
#Main Fields--------------------------------------------------------
name = fields.Char('Folio Number', readonly=True, index=True,
default=lambda self: _('New'))
partner_id = fields.Many2one('res.partner',
track_visibility='onchange')
closure_reason_id = fields.Many2one('room.closure.reason')
# partner_invoice_id = fields.Many2one('res.partner',
# string='Invoice Address',
# readonly=True, required=True,
# states={'draft': [('readonly', False)],
# 'sent': [('readonly', False)]},
# help="Invoice address for current sales order.")
# For being used directly in the Folio views
email = fields.Char('E-mail', related='partner_id.email')
mobile = fields.Char('Mobile', related='partner_id.mobile')
phone = fields.Char('Phone', related='partner_id.phone')
#Review: How to use state in folio?
state = fields.Selection([('draft', 'Pre-reservation'), ('confirm', 'Pending Entry'),
('booking', 'On Board'), ('done', 'Out'),
('cancelled', 'Cancelled')],
'State', readonly=True,
default=lambda *a: 'draft',
track_visibility='onchange')
room_lines = fields.One2many('hotel.reservation', 'folio_id',
readonly=False,
@@ -80,8 +61,6 @@ class HotelFolio(models.Model):
help="Hotel services detail provide to "
"customer and it will include in "
"main Invoice.")
hotel_invoice_id = fields.Many2one('account.invoice', 'Invoice')
company_id = fields.Many2one('res.company', 'Company')
currency_id = fields.Many2one('res.currency', related='pricelist_id.currency_id',
@@ -90,10 +69,50 @@ class HotelFolio(models.Model):
pricelist_id = fields.Many2one('product.pricelist',
string='Pricelist',
required=True,
readonly=True,
states={'draft': [('readonly', False)],
'sent': [('readonly', False)]},
help="Pricelist for current folio.")
reservation_type = fields.Selection([('normal', 'Normal'),
('staff', 'Staff'),
('out', 'Out of Service')],
'Type', default=lambda *a: 'normal')
channel_type = fields.Selection([('door', 'Door'),
('mail', 'Mail'),
('phone', 'Phone'),
('web', 'Web')], 'Sales Channel', default='door')
user_id = fields.Many2one('res.users', string='Salesperson', index=True,
track_visibility='onchange', default=lambda self: self.env.user)
date_order = fields.Datetime(
string='Order Date',
required=True, readonly=True, index=True,
states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
copy=False, default=fields.Datetime.now)
state = fields.Selection([
('draft', 'Quotation'),
('sent', 'Quotation Sent'),
('confirm', 'Confirmed'),
('done', 'Locked'),
('cancel', 'Cancelled'),
], string='Status',
readonly=True, copy=False,
index=True, track_visibility='onchange',
default='draft')
# Partner fields for being used directly in the Folio views---------
email = fields.Char('E-mail', related='partner_id.email')
mobile = fields.Char('Mobile', related='partner_id.mobile')
phone = fields.Char('Phone', related='partner_id.phone')
partner_internal_comment = fields.Text(string='Internal Partner Notes',
related='partner_id.comment')
#Payment Fields-----------------------------------------------------
payment_ids = fields.One2many('account.payment', 'folio_id',
readonly=True)
return_ids = fields.One2many('payment.return', 'folio_id',
readonly=True)
#Amount Fields------------------------------------------------------
pending_amount = fields.Monetary(compute='compute_amount',
store=True,
string="Pending in Folio")
@@ -103,50 +122,25 @@ class HotelFolio(models.Model):
invoices_paid = fields.Monetary(compute='compute_amount',
store=True, track_visibility='onchange',
string="Payments")
amount_untaxed = fields.Monetary(string='Untaxed Amount', store=True,
readonly=True, compute='_amount_all',
track_visibility='onchange')
amount_tax = fields.Monetary(string='Taxes', store=True,
readonly=True, compute='_amount_all')
amount_total = fields.Monetary(string='Total', store=True, readonly=True,
compute='_amount_all', track_visibility='always')
#Checkin Fields-----------------------------------------------------
booking_pending = fields.Integer('Booking pending',
compute='_compute_checkin_partner_count')
checkin_partner_count = fields.Integer('Checkin counter',
compute='_compute_checkin_partner_count')
checkin_partner_pending_count = fields.Integer('Checkin Pending',
compute='_compute_checkin_partner_count')
partner_internal_comment = fields.Text(string='Internal Partner Notes',
related='partner_id.comment')
internal_comment = fields.Text(string='Internal Folio Notes')
cancelled_reason = fields.Text('Cause of cancelled')
payment_ids = fields.One2many('account.payment', 'folio_id',
readonly=True)
return_ids = fields.One2many('payment.return', 'folio_id',
readonly=True)
prepaid_warning_days = fields.Integer(
'Prepaid Warning Days',
help='Margin in days to create a notice if a payment \
advance has not been recorded')
reservation_type = fields.Selection([('normal', 'Normal'),
('staff', 'Staff'),
('out', 'Out of Service')],
'Type', default=lambda *a: 'normal')
channel_type = fields.Selection([('door', 'Door'),
('mail', 'Mail'),
('phone', 'Phone'),
('web', 'Web')], 'Sales Channel', default='door')
num_invoices = fields.Integer(compute='_compute_num_invoices')
rooms_char = fields.Char('Rooms', compute='_computed_rooms_char')
segmentation_ids = fields.Many2many('res.partner.category',
string='Segmentation')
has_confirmed_reservations_to_send = fields.Boolean(
compute='_compute_has_confirmed_reservations_to_send')
has_cancelled_reservations_to_send = fields.Boolean(
compute='_compute_has_cancelled_reservations_to_send')
has_checkout_to_send = fields.Boolean(
compute='_compute_has_checkout_to_send')
# fix_price = fields.Boolean(compute='_compute_fix_price')
date_order = fields.Datetime(
string='Order Date',
required=True, readonly=True, index=True,
states={'draft': [('readonly', False)], 'sent': [('readonly', False)]},
copy=False, default=fields.Datetime.now)
#Invoice Fields-----------------------------------------------------
hotel_invoice_id = fields.Many2one('account.invoice', 'Invoice')
num_invoices = fields.Integer(compute='_compute_num_invoices')
invoice_ids = fields.Many2many('account.invoice', string='Invoices',
compute='_get_invoiced', readonly=True, copy=False)
invoice_status = fields.Selection([('upselling', 'Upselling Opportunity'),
@@ -156,17 +150,52 @@ class HotelFolio(models.Model):
string='Invoice Status',
compute='_compute_invoice_status',
store=True, readonly=True, default='no')
#~ partner_invoice_id = fields.Many2one('res.partner',
#~ string='Invoice Address',
#~ readonly=True, required=True,
#~ states={'draft': [('readonly', False)],
#~ 'sent': [('readonly', False)]},
#~ help="Invoice address for current sales order.")
#WorkFlow Mail Fields-----------------------------------------------
has_confirmed_reservations_to_send = fields.Boolean(
compute='_compute_has_confirmed_reservations_to_send')
has_cancelled_reservations_to_send = fields.Boolean(
compute='_compute_has_cancelled_reservations_to_send')
has_checkout_to_send = fields.Boolean(
compute='_compute_has_checkout_to_send')
#Generic Fields-----------------------------------------------------
internal_comment = fields.Text(string='Internal Folio Notes')
cancelled_reason = fields.Text('Cause of cancelled')
closure_reason_id = fields.Many2one('room.closure.reason')
prepaid_warning_days = fields.Integer(
'Prepaid Warning Days',
help='Margin in days to create a notice if a payment \
advance has not been recorded')
rooms_char = fields.Char('Rooms', compute='_computed_rooms_char')
segmentation_ids = fields.Many2many('res.partner.category',
string='Segmentation')
client_order_ref = fields.Char(string='Customer Reference', copy=False)
note = fields.Text('Terms and conditions')
# layout_category_id = fields.Many2one('sale.layout_category', string='Section')
user_id = fields.Many2one('res.users', string='Salesperson', index=True,
track_visibility='onchange', default=lambda self: self.env.user)
sequence = fields.Integer(string='Sequence', default=10)
# sale.order
amount_total = fields.Float(string='Total', store=True, readonly=True,
track_visibility='always')
@api.depends('room_lines.price_total','service_ids.price_total')
def _amount_all(self):
"""
Compute the total amounts of the SO.
"""
for record in self:
amount_untaxed = amount_tax = 0.0
amount_untaxed = sum(record.room_lines.mapped('price_subtotal')) + \
sum(record.service_ids.mapped('price_subtotal'))
amount_tax = sum(record.room_lines.mapped('price_tax')) + \
sum(record.service_ids.mapped('price_tax'))
record.update({
'amount_untaxed': record.pricelist_id.currency_id.round(amount_untaxed),
'amount_tax': record.pricelist_id.currency_id.round(amount_tax),
'amount_total': amount_untaxed + amount_tax,
})
def _computed_rooms_char(self):
for record in self:
@@ -317,7 +346,7 @@ class HotelFolio(models.Model):
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')
).next_by_code('hotel.folio') or _('New')
else:
vals['name'] = self.env['ir.sequence'].next_by_code('hotel.folio') or _('New')

View File

@@ -173,8 +173,7 @@ class HotelReservation(models.Model):
service_ids = fields.One2many('hotel.service', 'ser_room_line')
pricelist_id = fields.Many2one('product.pricelist',
related='folio_id.pricelist_id',
readonly="1")
related='folio_id.pricelist_id') #TODO: Warning Mens to update pricelist
checkin_partner_ids = fields.One2many('hotel.checkin.partner', 'reservation_id')
# TODO: As checkin_partner_count is a computed field, it can't not be used in a domain filer
# Non-stored field hotel.reservation.checkin_partner_count cannot be searched
@@ -259,6 +258,14 @@ class HotelReservation(models.Model):
readonly=True,
store=True,
compute='_compute_amount_reservation')
price_services = fields.Monetary(string='Services Total',
readonly=True,
store=True,
compute='_compute_amount_room_services')
price_room_services_set = fields.Monetary(string='Room Services Total',
readonly=True,
store=True,
compute='_compute_amount_set')
# FIXME discount per night
discount = fields.Float(string='Discount (%)', digits=dp.get_precision('Discount'), default=0.0)
@@ -290,6 +297,7 @@ class HotelReservation(models.Model):
board_services.append((0, False, {
'product_id': product.id,
'is_board_service': True,
'folio_id': vals.get('folio_id'),
}))
vals.update({'service_ids': board_services})
if self.compute_price_out_vals(vals):
@@ -327,6 +335,7 @@ class HotelReservation(models.Model):
board_services.append((0, False, {
'product_id': product.id,
'is_board_service': True,
'folio_id': record.folio_id.id or vals.get('folio_id')
}))
# NEED REVIEW: Why I need add manually the old IDs if board service is (0,0,(-)) ¿?¿?¿
record.update({'service_ids': [(6, 0, record.service_ids.ids)] + board_services})
@@ -610,6 +619,7 @@ class HotelReservation(models.Model):
vals = {
'product_id': product.id,
'is_board_service': True,
'folio_id': self.folio_id.id,
}
vals.update(self.env['hotel.service'].prepare_service_lines(
dfrom=self.checkin,
@@ -619,8 +629,10 @@ class HotelReservation(models.Model):
old_line_days=False))
board_services.append((0, False, vals))
other_services = self.service_ids.filtered(lambda r: r.is_board_service == False)
self.update({'service_ids': [(6, 0, other_services.ids)] + board_services})
for service in self.service_ids.filtered(lambda r: r.is_board_service == True):
service._compute_tax_ids()
service.price_unit = service._compute_price_unit()
"""
STATE WORKFLOW -----------------------------------------------------
@@ -706,6 +718,16 @@ class HotelReservation(models.Model):
"""
PRICE PROCESS ------------------------------------------------------
"""
@api.depends('service_ids.price_total')
def _compute_amount_room_services(self):
for record in self:
record.price_services = sum(record.mapped('service_ids.price_total'))
@api.depends('price_services','price_total')
def _compute_amount_set(self):
for record in self:
record.price_room_services_set = record.price_services + record.price_total
@api.multi
def compute_price_out_vals(self, vals):
"""

View File

@@ -5,6 +5,10 @@ from odoo import models, fields, api, _
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from datetime import timedelta
from odoo.exceptions import ValidationError
from odoo.addons import decimal_precision as dp
import logging
_logger = logging.getLogger(__name__)
class HotelService(models.Model):
_name = 'hotel.service'
@@ -50,31 +54,34 @@ class HotelService(models.Model):
product_qty = fields.Integer('Quantity')
days_qty = fields.Integer(compute="_compute_days_qty", store=True)
is_board_service = fields.Boolean()
pricelist_id = fields.Many2one(related='folio_id.pricelist_id')
# Non-stored related field to allow portal user to see the image of the product he has ordered
product_image = fields.Binary('Product Image', related="product_id.image", store=False)
channel_type = fields.Selection([
('door', 'Door'),
('mail', 'Mail'),
('phone', 'Phone'),
('call', 'Call Center'),
('web', 'Web')], 'Sales Channel')
currency_id = fields.Many2one('res.currency',
related='pricelist_id.currency_id',
string='Currency', readonly=True, required=True)
price_unit = fields.Float('Unit Price', required=True, digits=dp.get_precision('Product Price'), default=0.0)
tax_ids = fields.Many2many('account.tax', string='Taxes', domain=['|', ('active', '=', False), ('active', '=', True)])
discount = fields.Float(string='Discount (%)', digits=dp.get_precision('Discount'), default=0.0)
currency_id = fields.Many2one(related='folio_id.currency_id', store=True, string='Currency', readonly=True)
price_subtotal = fields.Monetary(string='Subtotal',
readonly=True,
store=True,
compute='_compute_amount_reservation')
compute='_compute_amount_service')
price_total = fields.Monetary(string='Total',
readonly=True,
store=True,
compute='_compute_amount_reservation')
compute='_compute_amount_service')
price_tax = fields.Float(string='Taxes',
readonly=True,
store=True,
compute='_compute_amount_reservation')
compute='_compute_amount_service')
@api.model
def create(self, vals):
vals.update(self._prepare_add_missing_fields(vals))
if self.compute_lines_out_vals(vals):
reservation = self.env['hotel.reservation'].browse(vals['ser_room_line'])
product = self.env['product.product'].browse(vals['product_id'])
@@ -114,6 +121,20 @@ class HotelService(models.Model):
res = super(HotelService, self).write(vals)
return res
@api.model
def _prepare_add_missing_fields(self, values):
""" Deduce missing required fields from the onchange """
res = {}
onchange_fields = ['price_unit','tax_ids']
if values.get('product_id'):
line = self.new(values)
if any(f not in values for f in onchange_fields):
line.onchange_product_calc_qty()
for field in onchange_fields:
if field not in values:
res[field] = line._fields[field].convert_to_write(line[field], line)
return res
@api.multi
def compute_lines_out_vals(self, vals):
"""
@@ -128,6 +149,26 @@ class HotelService(models.Model):
return True
return False
@api.multi
def _compute_tax_ids(self):
for record in self:
# If company_id is set, always filter taxes by the company
folio = self.folio_id or self.env.context.get('default_folio_id')
record.tax_id = record.product_id.taxes_id.filtered(lambda r: not record.company_id or r.company_id == folio.company_id)
@api.multi
def _get_display_price(self, product):
folio = self.folio_id or self.env.context.get('default_folio_id')
if folio.pricelist_id.discount_policy == 'with_discount':
return product.with_context(pricelist=folio.pricelist_id.id).price
product_context = dict(self.env.context, partner_id=folio.partner_id.id, date=folio.date_order, uom=self.product_id.uom_id.id)
final_price, rule_id = folio.pricelist_id.with_context(product_context).get_product_price_rule(self.product_id, self.product_qty or 1.0, folio.partner_id)
base_price, currency_id = self.with_context(product_context)._get_real_price_currency(product, rule_id, self.product_qty, product_id.uom_id, folio.pricelist_id.id)
if currency_id != folio.pricelist_id.currency_id.id:
base_price = self.env['res.currency'].browse(currency_id).with_context(product_context).compute(base_price, folio.pricelist_id.currency_id)
# negative discounts (= surcharge) are included in the display price
return max(base_price, final_price)
@api.onchange('product_id')
def onchange_product_calc_qty(self):
"""
@@ -135,11 +176,15 @@ class HotelService(models.Model):
configuration of the selected product, in per_day product configuration,
the qty is autocalculated and readonly based on service_lines qty
"""
if not self.product_id:
return
vals = {}
vals['product_qty'] = 1.0
for record in self:
if record.per_day and record.ser_room_line:
product = record.product_id
reservation = record.ser_room_line
record.update(self.prepare_service_lines(
vals.update(self.prepare_service_lines(
dfrom=reservation.checkin,
days=reservation.nights,
per_person=product.per_person,
@@ -148,6 +193,30 @@ class HotelService(models.Model):
if record.product_id.daily_limit > 0:
for day in record.service_line_ids:
day.no_free_resources()
"""
Compute tax and price unit
"""
self._compute_tax_ids()
vals['price_unit'] = self._compute_price_unit()
record.update(vals)
@api.multi
def _compute_price_unit(self):
"""
Compute tax and price unit
"""
folio = self.folio_id or self.env.context.get('default_folio_id')
product = self.product_id.with_context(
lang=folio.partner_id.lang,
partner=folio.partner_id.id,
quantity=self.product_qty,
date=folio.date_order,
pricelist=folio.pricelist_id.id,
uom=self.product_id.uom_id.id,
fiscal_position=False
)
return self.env['account.tax']._fix_tax_included_price_company(self._get_display_price(product), product.taxes_id, self.tax_ids, folio.company_id)
@api.model
def prepare_service_lines(self, **kwargs):
@@ -155,16 +224,15 @@ class HotelService(models.Model):
Prepare line and respect the old manual changes on lines
"""
cmds = [(5, 0, 0)]
old_lines_days = kwargs.get('old_lines_days')
old_line_days = kwargs.get('old_line_days')
total_qty = 0
day_qty = 1
if kwargs.get('per_person'): #WARNING: Change adults in reservation NOT update qty service!!
day_qty = kwargs.get('persons')
old_line_days = self.env['hotel.service.line'].browse(kwargs.get('old_line_days'))
for i in range(0, kwargs.get('days')):
idate = (fields.Date.from_string(kwargs.get('dfrom')) + timedelta(days=i)).strftime(
DEFAULT_SERVER_DATE_FORMAT)
if not old_lines_days or idate not in old_lines_days.mapped('date'):
if not old_line_days or idate not in old_line_days.mapped('date'):
cmds.append((0, False, {
'date': idate,
'day_qty': day_qty
@@ -176,15 +244,16 @@ class HotelService(models.Model):
total_qty = total_qty + old_line.day_qty
return {'service_line_ids': cmds, 'product_qty': total_qty}
@api.depends('qty_product', 'tax_id')
@api.depends('product_qty', 'discount', 'price_unit', 'tax_ids')
def _compute_amount_service(self):
"""
Compute the amounts of the service line.
"""
for record in self:
folio = record.folio_id or self.env.context.get('default_folio_id')
product = record.product_id
price = amount_room * (1 - (record.discount or 0.0) * 0.01)
taxes = record.tax_id.compute_all(price, record.currency_id, 1, product=product)
price = record.price_unit * (1 - (record.discount or 0.0) * 0.01)
taxes = record.tax_ids.compute_all(price, folio.currency_id, record.product_qty, product=product)
record.update({
'price_tax': sum(t.get('amount', 0.0) for t in taxes.get('taxes', [])),
'price_total': taxes['total_included'],
@@ -203,12 +272,20 @@ class HotelService(models.Model):
else:
vals = {'days_qty': 0}
record.update(vals)
@api.multi
def open_service_lines(self):
action = self.env.ref('hotel.action_hotel_services_form').read()[0]
action['views'] = [(self.env.ref('hotel.hotel_service_view_form').id, 'form')]
action['res_id'] = self.id
action['target'] = 'new'
return action
@api.constrains('qty_product')
def constrains_qty_per_day(self):
for record in self:
if record.per_day:
service_lines = self.env['hotel.service_line']
total_day_qty = sum(service_lines.with_context({'service_id': record.id}).mapped('day_qty'))
if record.qty_product != total_day_qty:
raise ValidationError (_('The quantity per line and per day does not correspond'))
#~ @api.constrains('product_qty')
#~ def constrains_qty_per_day(self):
#~ for record in self:
#~ if record.per_day:
#~ service_lines = self.env['hotel.service_line']
#~ total_day_qty = sum(service_lines.with_context({'service_id': record.id}).mapped('day_qty'))
#~ if record.product_qty != total_day_qty:
#~ raise ValidationError (_('The quantity per line and per day does not correspond'))

View File

@@ -135,6 +135,7 @@
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancel'))]}"/>
</group>
<group>
<field name="pricelist_id" domain="[('type','=','sale')]" />
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<field name="reservation_type" attrs="{'readonly':[('state','not in',('draft'))]}"/>
<field name="channel_type" attrs="{'required':[('reservation_type','=','normal')]}"/>
@@ -149,14 +150,12 @@
</group>
</group>
<group invisible="1">
<!-- <field name="pricelist_id" domain="[('type','=','sale')]" invisible="1"/> -->
<!-- <field name="partner_shipping_id" invisible="1" domain="[('parent_id','=',partner_id)]" /> -->
<!-- <field name="warehouse_id" string="Branch" invisible="1"/> -->
<field name="invoice_ids" invisible="1"/>
<field name="invoice_status" invisible="1" />
<!-- <field name="hotel_invoice_id" states='progress,done,cancel'
readonly="1" invisible="1" /> -->
<!-- <field name="fix_price" invisible="1" /> -->
</group>
<notebook colspan="4" col="1">
<page string="Lines">
@@ -287,19 +286,24 @@
</h3>
<group col="6">
<group string="General Info" name="contact_details" invisible="1">
<group string="General Info" name="contact_details" >
<field name="email" placeholder="email" widget="email" />
<field name="mobile" placeholder="mobile" widget="phone" />
<field name="phone" placeholder="phone" widget="phone" />
<field name="pricelist_id"/>
<field name="partner_internal_comment" string="Partner Note"/>
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancelled'))]}"/>
</group>
<group colspan="4" string="Reservation Details" name="reservation_details">
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancelled'))]}"/>
<field name="arrival_hour"/>
<field name="departure_hour"/>
<field name="nights" invisible="1"/>
<field name="board_service_id" />
<field name="name"/>
<field name="adults"/>
<field name="children"/>
<field name="room_type_id" on_change="1" options="{'no_create': True,'no_open': True}"
attrs="{'readonly':[('state','not in',('draft'))]}"/>
attrs="{'readonly':[('state','not in',('draft'))]}"/>
<field name="channel_type" attrs="{'required':[('reservation_type','not in',('staff','out'))]}"/>
</group>
<group class="oe_subtotal_footer" style="margin-right: 20px; !important" colspan="2" name="reservation_total" string="Amounts">
@@ -331,8 +335,6 @@
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<!-- <field name="check_rooms" invisible="1"/> -->
<field name="checkin_partner_pending_count" invisible="1"/>
<!-- <field name="pricelist_id" invisible="1"/> -->
<field name="nights" invisible="1"/>
</group>
<notebook>
<page name="days" string="Service and Days">
@@ -417,7 +419,6 @@
domain="[('sale_ok', '=', True)]"
options="{'create': False, 'create_edit': False}" />
<field name="name"/>
<field name="pricelist_id"/>
<field name="ser_room_line" options="{'create': False, 'create_edit': False}"/>
<!-- <field name="product_uom_qty"
string="Ordered Qty"
@@ -447,6 +448,15 @@
<field name="channel_type" sttrs="{'invisible':[('channel_type', '!=', 'call')]"/>
</tree>
</field>
<group colspan="2" class="oe_subtotal_footer oe_right">
<field name="amount_untaxed" sum="Untaxed amount" widget='monetary' />
<field name="amount_tax" widget='monetary' />
<div class="oe_subtotal_footer_separator oe_inline">
<label for="amount_total" />
</div>
<field name="amount_total" nolabel="1" sum="Total amount"
widget='monetary' />
</group>
<div class="oe_clear" />
<group>
<field name="note" />

View File

@@ -183,18 +183,18 @@
<field name="email" placeholder="email" widget="email" />
<field name="mobile" placeholder="mobile" widget="phone" />
<field name="phone" placeholder="phone" widget="phone" />
<field name="pricelist_id"/>
<field name="partner_internal_comment" string="Partner Note"/>
<field name="cancelled_reason" attrs="{'invisible':[('state','not in',('cancelled'))]}"/>
</group>
<group colspan="4" string="Reservation Details" name="reservation_details">
<field name="arrival_hour"/>
<field name="departure_hour"/>
<field name="nights" invisible="1"/>
<field name="board_service_id" />
<field name="name"/>
<field name="adults"/>
<field name="children"/>
<!-- <field name="room_type_id" on_change="1" options="{'no_create': True,'no_open': True}"
attrs="{'readonly':[('state','not in',('draft'))]}"/> -->
<field name="room_type_id" on_change="1" options="{'no_create': True,'no_open': True}"
attrs="{'readonly':[('state','not in',('draft'))]}"/>
<field name="channel_type" attrs="{'required':[('reservation_type','not in',('staff','out'))]}"/>
@@ -224,6 +224,8 @@
<!-- <field name="customer_lead" invisible="1"/> -->
<field name="currency_id" invisible="1"/>
<field name="price_subtotal" widget="monetary"/>
<field name="price_services" widget="monetary"/>
<field name="price_room_services_set" widget="monetary"/>
</group>
</group>
<field name="folio_internal_comment" nolabel="1" placeholder="Reservation Notes"/>
@@ -231,29 +233,36 @@
<field name="company_id" options="{'no_create': True}" groups="base.group_multi_company"/>
<!-- <field name="check_rooms" invisible="1"/> -->
<field name="checkin_partner_pending_count" invisible="1"/>
<!-- <field name="pricelist_id" invisible="1"/> -->
<field name="nights" invisible="1"/>
<!-- <field name="product_uom" string="Rent(UOM)" invisible="1" /> -->
</group>
<notebook>
<page name="days" string="Service and Days">
<group col="9">
<group colspan="6" string="Reservation Services" name="reservation_services" attrs="{'invisible': [('folio_id','=',False)]}">
<group string="Reservation Services" name="reservation_services" attrs="{'invisible': [('folio_id','=',False)]}">
<field name="service_ids"
nolabel="1" style="padding-right:10px !important;">
<!-- <field name="service_ids"> -->
<tree string="Services">
context="{'default_ser_room_line': active_id, 'default_folio_id': folio_id}"
nolabel="1">
<tree string="Services" editable="bottom">
<!-- <field name="sequence" widget="handle"/> -->
<field name="per_day" />
<field name="is_board_service" />
<field name="per_day" invisible="1"/>
<field name="is_board_service" invisible="1" />
<field name="folio_id" invisible="1"/>
<field name="product_id"
domain="[('sale_ok', '=', True)]"
options="{'create': False, 'create_edit': False}" />
<!-- <field name="layout_category_id" groups="sale.group_sale_layout"/> -->
<field name="name"/>
<field name="product_qty" attrs="{'readonly': [('per_day','=',True)]}" force_save="1"/>
<field name="days_qty" />
<field name="product_qty" attrs="{'readonly': [('per_day','=',True)]}" force_save="1"/>
<button type="object" class="oe_stat_button"
id="go_service_lines" icon="fa fa-2x fa-bars"
name="open_service_lines"
attrs="{'invisible': [('per_day','=',False)]}"/>
<field name="days_qty" invisible="1"/>
<field name="price_unit" />
<field name="discount" />
<field name="tax_ids" widget="many2many_tags"/>
<field name="price_subtotal" />
<field name="price_tax" />
<field name="price_total" />
<field name="service_line_ids" invisible="1">
<tree string="Days" >
<field name="date" />
@@ -261,26 +270,9 @@
</tree>
</field>
</tree>
<form string="Services">
<!-- <field name="sequence" widget="handle"/> -->
<field name="per_day" />
<field name="folio_id" invisible="1"/>
<field name="product_id"
domain="[('sale_ok', '=', True)]"
options="{'create': False, 'create_edit': False}" />
<!-- <field name="layout_category_id" groups="sale.group_sale_layout"/> -->
<field name="name"/>
<field name="product_qty" attrs="{'readonly': [('per_day','=',True)]}" force_save="1"/>
<field name="service_line_ids">
<tree string="Days" >
<field name="date" />
<field name="day_qty" />
</tree>
</field>
</form>
</field>
</group>
<group colspan="4" string="Days" name="days">
<group string="Days" name="days">
<field name="reservation_line_ids" nolabel="1">
<tree create="false" delete="false" editable="bottom">
<field name="date" />
@@ -289,7 +281,6 @@
</tree>
</field>
</group>
</group>
</page>
<page name="others" string="Others">
<group>

View File

@@ -9,19 +9,29 @@
<form string="Reservation Service">
<sheet>
<h1>
<label string="Service" />
<field name="name" select="1" />
<field name="name" readonly="1"/>
</h1>
<group>
<field name="product_id" />
<field name="product_qty" />
</group>
<group>
<field name="price_subtotal" />
<field name="price_total" />
</group>
<field name="service_line_ids">
<tree string="Days" >
<field name="per_day" invisible="1"/>
<field name="is_board_service" invisible="1" />
<field name="folio_id" invisible="1"/>
<field name="product_id"
domain="[('sale_ok', '=', True)]"
options="{'create': False, 'create_edit': False}"
invisible="1" />
<!-- <field name="layout_category_id" groups="sale.group_sale_layout"/> -->
<field name="product_qty" invisible="0"
attrs="{'readonly': [('per_day','=',True)]}"
force_save="1"/>
<field name="days_qty" invisible="0"/>
<field name="price_unit" invisible="1" />
<field name="discount" invisible="1"/>
<field name="tax_ids" widget="many2many_tags"
invisible="1"/>
<field name="price_subtotal" invisible="1"/>
<field name="price_tax" invisible="1"/>
<field name="price_total" invisible="1"/>
<field name="service_line_ids" nolabel="1">
<tree string="Days" editable="bottom" >
<field name="date" />
<field name="day_qty" />
</tree>
@@ -68,36 +78,10 @@
<field name="name">Hotel Services</field>
<field name="res_model">hotel.service</field>
<field name="view_type">form</field>
<!-- <field name="context">{'default_isservice':1}
</field> -->
<field name="view_mode">tree,form</field>
</record>
<menuitem name="Services" id="menu_open_hotel_services_form"
action="action_hotel_services_form" sequence="8"
parent="hotel.menu_hotel_service" />
<!-- Categories for Services -->
<record model="ir.actions.act_window" id="hotel_service_category_action">
<field name="name">Services by Category</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">product.category</field>
<!-- <field name="domain">[('parent_id','=',False),('isservicetype','=',True)]
</field> -->
<field name="view_type">tree</field>
<!-- <field name="view_id" ref="product_category_tree_view" /> -->
</record>
<!--record id="ir_service_category_open" model='ir.default'>
<field eval="'tree_but_open'" name="key2"/>
<field eval="'product.category'" name="model"/>
<field name="name">Services</field>
<field eval="'ir.actions.act_window,%d'%action_room_cate" name="value"/>
</record-->
<menuitem name="Services by Type" id="menu_hotel_service_category_action"
action="hotel_service_category_action" sequence="10"
parent="hotel.menu_hotel_service" />
</odoo>