You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
556 lines
26 KiB
556 lines
26 KiB
# -*- coding: utf-8 -*-
|
|
###############################################################################
|
|
#
|
|
# Cybrosys Technologies Pvt. Ltd.
|
|
#
|
|
# Copyright (C) 2024-TODAY Cybrosys Technologies(<https://www.cybrosys.com>)
|
|
# Author: Fathima Mazlin AM (odoo@cybrosys.com)
|
|
#
|
|
# You can modify it under the terms of the GNU AFFERO
|
|
# GENERAL PUBLIC LICENSE (AGPL v3), Version 3.
|
|
#
|
|
# 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 AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details.
|
|
#
|
|
# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
# (AGPL v3) along with this program.
|
|
# If not, see <http://www.gnu.org/licenses/>.
|
|
#
|
|
###############################################################################
|
|
from odoo import api, fields, models, _
|
|
from odoo.exceptions import UserError, ValidationError
|
|
|
|
|
|
class VenueBooking(models.Model):
|
|
"""Model for managing the Venue Booking"""
|
|
_name = 'venue.booking'
|
|
_inherit = ['mail.thread', 'mail.activity.mixin']
|
|
_description = 'Venue Reservation'
|
|
|
|
name = fields.Char(string="Name", help="Name of the venue type")
|
|
ref = fields.Char(string='Ref', readonly=True,
|
|
help="Name of the venue that created as sequencing")
|
|
venue_id = fields.Many2one('venue', string='Venue',
|
|
help="Venue for the Event", required=True)
|
|
venue_type_id = fields.Many2one('venue.type', 'Venue Type',
|
|
related='venue_id.venue_type_id',
|
|
readonly=True,
|
|
help='Used to choose the type of the'
|
|
' particular venue')
|
|
image = fields.Binary("Image", attachment=True,
|
|
related='venue_type_id.image',
|
|
help="This field holds the image used as "
|
|
"image for the event, limited to 1080x720px.")
|
|
partner_id = fields.Many2one('res.partner', string="Customer",
|
|
required=True,
|
|
help='Used to Choose the Booking Person')
|
|
date = fields.Date(string="Date", default=fields.Date.today, required=True,
|
|
help='Date field for booking the Venue')
|
|
currency_id = fields.Many2one('res.currency', readonly=True,
|
|
string='Currency',
|
|
default=lambda self:
|
|
self.env.user.company_id.currency_id,
|
|
help='Currency field for booking Venue')
|
|
start_date = fields.Datetime(string="Start date",
|
|
default=lambda self: fields.datetime.now(),
|
|
required=True,
|
|
help='Venue Booking Start Date')
|
|
end_date = fields.Datetime(string="End date", required=True,
|
|
help='Venue Booking End Date')
|
|
state = fields.Selection([('draft', 'Draft'),
|
|
('confirm', 'Confirmed'),
|
|
('invoice', 'Invoiced'),
|
|
('close', 'Close'), ('cancel', 'Canceled')],
|
|
string="State", default="draft",
|
|
help="State of venue booking")
|
|
booking_type = fields.Selection([('day', 'Day'),
|
|
('hour', 'Hours')], string='Booking Type',
|
|
default='day', help='The selection field '
|
|
'for Booking Type')
|
|
venue_booking_line_ids = fields.One2many('venue.booking.line',
|
|
'venue_booking_id',
|
|
string="Venues",
|
|
help='Booking Line for '
|
|
'the given venue')
|
|
note = fields.Text(string='Terms and conditions',
|
|
help='The note field for Venue Booking')
|
|
pending_invoice = fields.Boolean(string="Invoice Pending",
|
|
compute='_compute_pending_invoice',
|
|
help='Find out is there any '
|
|
'pending invoice')
|
|
total = fields.Monetary(string="Total Amount", store=True,
|
|
compute='_compute_total_amount',
|
|
help='Total amount for the Venue Booking')
|
|
booking_charge_per_day = fields.Float(string="Booking Charge Per Day",
|
|
related='venue_id.venue_charge_day',
|
|
help='Field for adding Booking '
|
|
'Charge Per Day')
|
|
booking_charge_per_hour = fields.Float(
|
|
string="Booking Charge Per Hour",
|
|
related='venue_id.venue_charge_hour',
|
|
help='Field for adding Booking Charge Per hour')
|
|
booking_charge = fields.Float(string="Venue Amenities Charge",
|
|
compute='_compute_booking_charge',
|
|
help='Compute the total Booking cost '
|
|
'includes the amenities')
|
|
days_difference = fields.Integer(string='Days Difference',
|
|
compute='_compute_days_difference',
|
|
help='Number of Days to '
|
|
'Booking the venue')
|
|
invoice_count = fields.Integer(string="Invoice Count",
|
|
compute='_compute_invoice_count',
|
|
help='Total invoice count')
|
|
is_additional_charge = fields.Boolean(string="Add Extra Charge?",
|
|
help='Add additional charge '
|
|
'for the booking')
|
|
|
|
@api.constrains('venue_booking_line_ids')
|
|
def _check_venue_booking_line_ids(self):
|
|
"""Check if the venue bookings line contains already taken amenities"""
|
|
amenities_list = []
|
|
name_list = []
|
|
if self.venue_id.venue_line_ids:
|
|
amenities = self.venue_id.venue_line_ids.mapped('amenities_id')
|
|
for line in self.venue_booking_line_ids:
|
|
if line.amenity_id in amenities:
|
|
amenities_list.append(line.amenity_id)
|
|
name_list.append(line.amenity_id.name)
|
|
if amenities_list:
|
|
names = ', '.join(name_list)
|
|
raise ValidationError(
|
|
_("Amenities %s are already Include in Your Venue Booking %s"
|
|
% (str(names), str(self.venue_id.name))))
|
|
|
|
@api.model
|
|
def create(self, values):
|
|
"""Create method for sequencing and checking dates
|
|
while Booking the Venues"""
|
|
date = values['date']
|
|
partner_name = self.env['res.partner'].browse(
|
|
values['partner_id']).name
|
|
values['name'] = '%s- %s' % (partner_name, date)
|
|
values['ref'] = self.env['ir.sequence'].next_by_code(
|
|
'venue.booking.sequence')
|
|
res = super().create(values)
|
|
return res
|
|
|
|
@api.onchange('start_date', 'end_date')
|
|
def _onchange_booking_dates(self):
|
|
"""Checking dates while Booking the Venues based on the
|
|
changes of the Dates"""
|
|
if self.venue_id:
|
|
booking = self.env['venue.booking'].search(
|
|
[('start_date', '<', self.end_date),
|
|
('end_date', '>', self.start_date),
|
|
('venue_id', '=', self.venue_id.id)])
|
|
if booking:
|
|
raise ValidationError(
|
|
"Venue is not available for the selected time range.")
|
|
|
|
@api.constrains('start_date', 'end_date')
|
|
def constrains_dates(self):
|
|
for rec in self:
|
|
start_date = rec.start_date
|
|
end_date = rec.end_date
|
|
if start_date >= end_date:
|
|
raise UserError(_('Start date must be less than End date'))
|
|
|
|
def get_booking_dates(self, start_date, end_date, venue_id):
|
|
"""Checking dates while Booking the Venues based on the changes
|
|
of the Dates"""
|
|
result = 0
|
|
date_result = 0
|
|
venue = self.env['venue'].browse(venue_id)
|
|
if start_date >= end_date:
|
|
date_result = 1
|
|
else:
|
|
date_result = 0
|
|
if date_result == 0:
|
|
booking = self.env['venue.booking'].sudo().search(
|
|
[('venue_id', '=', venue.id),
|
|
('start_date', '<', end_date),
|
|
('end_date', '>', start_date),
|
|
])
|
|
if booking:
|
|
result = 1
|
|
else:
|
|
result = 0
|
|
data = {
|
|
'result': result,
|
|
"date_result": date_result,
|
|
}
|
|
return data
|
|
|
|
@api.depends('start_date', 'end_date')
|
|
def _compute_days_difference(self):
|
|
"""Compute the difference between start and end dates for
|
|
Calculating the days"""
|
|
for record in self:
|
|
if record.start_date and record.end_date:
|
|
delta = record.end_date - record.start_date
|
|
record.days_difference = delta.days
|
|
else:
|
|
record.days_difference = 0
|
|
|
|
@api.depends('booking_charge', 'venue_id')
|
|
def _compute_booking_charge(self):
|
|
"""Compute booking charge for the given venue with the Amenities"""
|
|
for rec in self:
|
|
rec.booking_charge = rec.venue_id.price_subtotal if rec.venue_id else 0.0
|
|
|
|
@api.depends('venue_booking_line_ids', 'venue_booking_line_ids.state')
|
|
def _compute_pending_invoice(self):
|
|
"""Compute function for finding the pending Invoices"""
|
|
for pending in self:
|
|
pending.pending_invoice = any(
|
|
not line.is_invoiced and line.state == "done" for line in
|
|
pending.venue_booking_line_ids)
|
|
|
|
@api.depends('venue_booking_line_ids.sub_total', 'booking_charge_per_hour',
|
|
'booking_charge_per_day', 'is_additional_charge', 'booking_type')
|
|
def _compute_total_amount(self):
|
|
"""Compute total amount of bookings with the Charge of the
|
|
Particular venue"""
|
|
total = sum(item.sub_total for item in self.venue_booking_line_ids)
|
|
for rec in self:
|
|
if rec.booking_type == 'day':
|
|
total += (rec.booking_charge_per_day * rec.days_difference)
|
|
if rec.is_additional_charge:
|
|
if rec.venue_id.additional_charge_day != 0.0:
|
|
total += rec.venue_id.additional_charge_day
|
|
is_extra = self.env['ir.config_parameter'].sudo(). \
|
|
get_param('venue_booking_management.is_extra')
|
|
if is_extra:
|
|
amount = self.env['ir.config_parameter'].sudo(). \
|
|
get_param('venue_booking_management.extra_amount')
|
|
total += float(amount)
|
|
elif rec.booking_type == 'hour':
|
|
total += (rec.booking_charge_per_hour * (
|
|
rec.days_difference * 24))
|
|
if rec.is_additional_charge:
|
|
if rec.venue_id.additional_charge_hour != 0.0:
|
|
total += rec.venue_id.additional_charge_hour
|
|
is_extra = self.env['ir.config_parameter'].sudo(). \
|
|
get_param('venue_booking_management.is_extra')
|
|
if is_extra:
|
|
amount = self.env['ir.config_parameter'].sudo(). \
|
|
get_param(
|
|
'venue_booking_management.extra_amount')
|
|
total += float(amount)
|
|
rec.total = total + rec.booking_charge
|
|
|
|
def action_booking_confirm(self):
|
|
"""Button action to confirm"""
|
|
for booking in self:
|
|
bookings = self.env['venue.booking'].search([
|
|
('venue_id', '=', booking.venue_id.id),
|
|
('start_date', '<', booking.end_date),
|
|
('end_date', '>', booking.start_date),
|
|
('id', '!=', booking.id), # Exclude the current record itself
|
|
])
|
|
if bookings:
|
|
raise ValidationError(
|
|
"Booking dates overlap with existing bookings.")
|
|
else:
|
|
self.state = "confirm"
|
|
|
|
def action_reset_to_draft(self):
|
|
"""Button action to reset"""
|
|
self.state = "draft"
|
|
|
|
def action_send_confirmation_mail(self):
|
|
"""Button action to send confirmation mail"""
|
|
template = self.env.ref(
|
|
'venue_booking_management.'
|
|
'mail_template_notify_venue_booking').sudo()
|
|
template.send_mail(self._origin.id, force_send=True,
|
|
email_values={
|
|
'email_to': self.partner_id.email})
|
|
|
|
def action_booking_invoice_create(self):
|
|
"""Button action to create related invoice"""
|
|
invoice_id = self.env['account.move'].search(
|
|
[('invoice_origin', '=', self.ref), ('state', '=', 'draft')])
|
|
amenity_lists = []
|
|
|
|
def add_charge(name, price_unit, quantity=1):
|
|
amenity_lists.append({
|
|
'name': name,
|
|
'price_unit': price_unit,
|
|
'quantity': quantity,
|
|
})
|
|
|
|
if self.booking_type == 'day':
|
|
if self.is_additional_charge:
|
|
total = self.booking_charge_per_day + self.venue_id.\
|
|
additional_charge_day
|
|
else:
|
|
total = self.booking_charge_per_day
|
|
elif self.booking_type == 'hour':
|
|
if self.is_additional_charge:
|
|
total = (self.booking_charge_per_hour * (self.days_difference *
|
|
24)) + \
|
|
self.venue_id.additional_charge_hour
|
|
else:
|
|
total = (self.booking_charge_per_hour * (self.days_difference *
|
|
24))
|
|
else:
|
|
total = 0
|
|
add_charge('Amenities charge', self.booking_charge)
|
|
add_charge('Booking Charges', total)
|
|
for rec in self.venue_booking_line_ids:
|
|
add_charge(rec.amenity_id.name, rec.amount, rec.quantity)
|
|
if self.is_additional_charge:
|
|
is_extra = self.env['ir.config_parameter'].sudo(). \
|
|
get_param('venue_booking_management.is_extra')
|
|
if is_extra:
|
|
amount = self.env['ir.config_parameter'].sudo(). \
|
|
get_param('venue_booking_management.extra_amount')
|
|
amenity_lists.append({
|
|
'name': 'Extra charges',
|
|
'price_unit': amount,
|
|
'quantity': '1',
|
|
})
|
|
invoice_vals = {
|
|
'move_type': 'out_invoice',
|
|
'partner_id': self.partner_id.id,
|
|
'invoice_origin': self.ref,
|
|
'invoice_line_ids': [(0, 0, line) for line in amenity_lists],
|
|
}
|
|
if not invoice_id:
|
|
invoice = self.env['account.move'].create([invoice_vals])
|
|
self.state = "invoice"
|
|
return {
|
|
'name': 'Invoice',
|
|
'view_mode': 'form',
|
|
'res_id': invoice.id,
|
|
'res_model': 'account.move',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
}
|
|
else:
|
|
# Unlink existing lines
|
|
invoice_id.invoice_line_ids.unlink()
|
|
invoice_id.write(
|
|
{'invoice_line_ids': [(0, 0, line) for line in amenity_lists]})
|
|
self.state = "invoice"
|
|
return {
|
|
'name': 'Invoice',
|
|
'view_mode': 'form',
|
|
'res_id': invoice_id.id,
|
|
'res_model': 'account.move',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
}
|
|
|
|
def action_view_invoice(self):
|
|
"""Smart button to view the Corresponding Invoices for
|
|
the Venue Booking"""
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'Invoice',
|
|
'view_mode': 'tree,form',
|
|
'res_model': 'account.move',
|
|
'target': 'current',
|
|
'domain': [('invoice_origin', '=', self.ref)],
|
|
'context': {"create": False},
|
|
}
|
|
|
|
def _compute_invoice_count(self):
|
|
"""Function to count invoice"""
|
|
for record in self:
|
|
record.invoice_count = self.env['account.move']. \
|
|
search_count([('invoice_origin', '=', self.ref)])
|
|
|
|
def action_booking_cancel(self):
|
|
"""Button action to move the cancel state"""
|
|
self.state = "cancel"
|
|
|
|
def action_booking_close(self):
|
|
"""Button action to close the records"""
|
|
if any(not line.is_invoiced for line in self.venue_booking_line_ids):
|
|
raise ValidationError(_('You can close The Booking only when all '
|
|
'Procedure is Done and Invoiced'))
|
|
else:
|
|
self.state = "close"
|
|
|
|
@api.model
|
|
def get_total_booking(self):
|
|
"""Function to get total booking, distance and invoice
|
|
amount details"""
|
|
total_booking = self.env['venue.booking'].search_count([])
|
|
booking_ids = self.env['venue.booking'].search(
|
|
[('state', 'not in', ['draft', 'cancel', 'close'])])
|
|
invoice_ids = self.env['venue.booking']. \
|
|
search([('state', '=', 'invoice')]).mapped('total')
|
|
venue_ids = self.env['venue'].search_count([])
|
|
return {'total_booking': total_booking,
|
|
'total_invoice': sum(invoice_ids),
|
|
'total_amount': sum(booking_ids.mapped('total')),
|
|
'total_venue': venue_ids}
|
|
|
|
@api.model
|
|
def get_top_venue(self):
|
|
"""Function to return top venue and customer details query to js"""
|
|
self.env.cr.execute('''select fv.name,count(tb.name) from venue_booking as tb
|
|
inner join venue as fv on fv.id = tb.venue_id
|
|
group by fv.name order by count(tb.name) desc limit 10''')
|
|
venue = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select pr.name,count(tb.name) from venue_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by pr.name order by count(tb.name) desc limit 10''')
|
|
customer = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select tb.ref, pr.name, tb.date from
|
|
venue_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
where tb.date >= '%s' and tb.state = 'invoice'
|
|
order by tb.date''' % fields.date.today())
|
|
upcoming = self.env.cr.dictfetchall()
|
|
return {'venue': venue, 'customer': customer, 'upcoming': upcoming}
|
|
|
|
@api.model
|
|
def get_booking_analysis(self):
|
|
"""Function to return customer details to js for graph view"""
|
|
self.env.cr.execute('''select pr.name,sum(tb.total) from venue_booking as tb
|
|
inner join res_partner as pr on pr.id = tb.partner_id
|
|
group by pr.name order by sum(tb.total)''')
|
|
booking = self.env.cr.dictfetchall()
|
|
count = []
|
|
customer = []
|
|
for record in booking:
|
|
customer.append(record.get('name'))
|
|
count.append(record.get('sum'))
|
|
value = {'name': customer, 'count': count}
|
|
return value
|
|
|
|
@api.model
|
|
def get_venue_analysis(self):
|
|
"""Function to return truck details to js for graph view"""
|
|
self.env.cr.execute('''select fv.name,sum(tb.total) from venue_booking as tb
|
|
inner join venue as fv on fv.id = tb.venue_id
|
|
group by fv.name order by sum(tb.total)''')
|
|
booking = self.env.cr.dictfetchall()
|
|
count = []
|
|
customer = []
|
|
for record in booking:
|
|
customer.append(record.get('name'))
|
|
count.append(record.get('sum'))
|
|
return {'name': customer, 'count': count}
|
|
|
|
@api.model
|
|
def get_select_filter(self, option):
|
|
"""Function to filter data on the bases of the year"""
|
|
if option == 'year':
|
|
create_date = '''create_date BETWEEN date_trunc('year', now()) AND now()'''
|
|
elif option == 'month':
|
|
create_date = '''create_date BETWEEN date_trunc('month', now()) AND now()'''
|
|
elif option == 'week':
|
|
create_date = '''create_date between date_trunc('week', now()) and now()'''
|
|
elif option == 'day':
|
|
create_date = '''create_date BETWEEN date_trunc('day', now()) AND now()'''
|
|
self.env.cr.execute('''select count(*) from venue_booking
|
|
where %s''' % create_date)
|
|
booking = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select sum(total) from venue_booking
|
|
where %s''' % create_date)
|
|
amount = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select sum(total) from venue_booking
|
|
where state = 'invoice' and %s''' % create_date)
|
|
invoice = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''select count(*) from venue
|
|
where %s''' % create_date)
|
|
venue_count = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''SELECT fv.name, COUNT(tb.name) AS name_count
|
|
FROM venue_booking AS tb
|
|
INNER JOIN venue AS fv ON fv.id = tb.venue_id
|
|
where tb.%s
|
|
GROUP BY fv.name
|
|
ORDER BY name_count DESC
|
|
LIMIT 10''' % create_date)
|
|
venue = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''SELECT pr.name, COUNT(tb.name) AS name_count
|
|
FROM venue_booking AS tb
|
|
INNER JOIN res_partner AS pr ON pr.id = tb.partner_id
|
|
where tb.%s
|
|
GROUP BY pr.name
|
|
ORDER BY name_count DESC
|
|
LIMIT 10''' % create_date)
|
|
customer = self.env.cr.dictfetchall()
|
|
self.env.cr.execute('''SELECT pr.name, COUNT(pr.name) AS count, SUM(tb.total) AS total_sum
|
|
FROM venue_booking AS tb
|
|
INNER JOIN res_partner AS pr ON pr.id = tb.partner_id
|
|
WHERE tb.%s
|
|
GROUP BY pr.name
|
|
''' % create_date)
|
|
cust_invoice = self.env.cr.dictfetchall()
|
|
cust_invoice_name = []
|
|
cust_invoice_sum = []
|
|
cust_invoice_count = []
|
|
for record in cust_invoice:
|
|
cust_invoice_name.append(record.get('name'))
|
|
cust_invoice_count.append(record.get('count'))
|
|
cust_invoice_sum.append(record.get('sum'))
|
|
self.env.cr.execute('''SELECT fv.name, SUM(tb.total) AS total_sum
|
|
FROM venue_booking AS tb
|
|
INNER JOIN venue AS fv ON fv.id = tb.venue_id
|
|
where tb.%s
|
|
GROUP BY fv.name;
|
|
''' % create_date)
|
|
truck_invoice = self.env.cr.dictfetchall()
|
|
truck_invoice_name = []
|
|
truck_invoice_sum = []
|
|
for record in truck_invoice:
|
|
truck_invoice_name.append(record.get('name'))
|
|
truck_invoice_sum.append(record.get('total_sum'))
|
|
return {'booking': booking, 'amount': amount,
|
|
'invoice': invoice, 'venue': venue, 'venue_count': venue_count,
|
|
'customer': customer,
|
|
'cust_invoice_name': cust_invoice_name,
|
|
'cust_invoice_count': cust_invoice_count, 'cust_invoice_sum':
|
|
cust_invoice_sum, 'truck_invoice_name': truck_invoice_name,
|
|
'truck_invoice_sum': truck_invoice_sum,
|
|
}
|
|
|
|
|
|
class VenueBookingLine(models.Model):
|
|
"""Model to manage the Venue Booking lines of the Venue Reservation"""
|
|
_name = 'venue.booking.line'
|
|
_description = "Venue Booking"
|
|
|
|
venue_booking_id = fields.Many2one('venue.booking',
|
|
string="Venue Booking",
|
|
help='The relation added for the venue Booking ')
|
|
state = fields.Selection([('done', 'Done'), ('pending', 'Pending')],
|
|
string="State", default="pending",
|
|
readonly=True,
|
|
help="The state of the venue Booking line")
|
|
currency_id = fields.Many2one('res.currency', readonly=True,
|
|
default=lambda self:
|
|
self.env.user.company_id.currency_id,
|
|
string="Currency",
|
|
help="The currency of the booking line")
|
|
is_invoiced = fields.Boolean(string="Invoiced", readonly=True,
|
|
help="The boolean value used for finding the "
|
|
"venue booking is invoiced or not")
|
|
venue_type_id = fields.Many2one('venue.type',
|
|
string="Related Venue Type",
|
|
related='venue_booking_id.venue_type_id',
|
|
help="The venue type of the booking line")
|
|
amenity_id = fields.Many2one('amenities', string='Amenities',
|
|
help='The relational field for the booking '
|
|
'line with the amenities model')
|
|
quantity = fields.Float(string="Quantity", default=1,
|
|
help="Quantity of the Amenities")
|
|
amount = fields.Float(string="Amount", help="Amount of the Amenities",
|
|
related='amenity_id.amount')
|
|
sub_total = fields.Float(string="Sub Total",
|
|
compute="_compute_extra_sub_total",
|
|
readonly=True, help="Sub Total of the Values")
|
|
|
|
@api.depends('quantity', 'amount')
|
|
def _compute_extra_sub_total(self):
|
|
"""Compute function for the Amenities"""
|
|
for booking in self:
|
|
booking.sub_total = booking.quantity * booking.amount
|
|
|