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.
152 lines
6.7 KiB
152 lines
6.7 KiB
# -*- coding: utf-8 -*-
|
|
from datetime import datetime as dtdatetime, time as dttime
|
|
from odoo import models, fields, api
|
|
from pytz import timezone, utc
|
|
|
|
def float2time(fhours, seconds=False):
|
|
hrs = int(fhours)
|
|
fmin = (fhours - hrs) * 60
|
|
min = int(fmin)
|
|
sec = 0
|
|
if seconds:
|
|
fsec = (fmin - min) * 60
|
|
sec = int(fsec)
|
|
return dttime(hrs, min, sec)
|
|
|
|
|
|
class RestaurantBooking(models.Model):
|
|
_name = 'restaurant.booking'
|
|
_description = "Restaurant booking"
|
|
_order = 'date, time_start, count desc'
|
|
|
|
@api.model
|
|
def default_get(self, fields_list):
|
|
defaults = super().default_get(fields_list)
|
|
start = self.env.context.get('default_datetime_start', False)
|
|
table_id = self.env.context.get('default_table_id', False)
|
|
if start:
|
|
defaults['date'] = start[:10]
|
|
dtstart = fields.Datetime.context_timestamp(self, fields.Datetime.to_datetime(start))
|
|
tstart = dtstart.hour
|
|
if tstart:
|
|
defaults['time_start'] = tstart
|
|
if table_id:
|
|
defaults['table_ids'] = [(6, 0, [table_id])]
|
|
return defaults
|
|
|
|
name = fields.Char(string="Name", required=True)
|
|
date = fields.Date(string="Date", required=True)
|
|
time_start = fields.Float(string="Start", required=True, group_operator=False)
|
|
time_stop = fields.Float(string="Stop", compute="_get_time_stop", store=True, inverse="_set_time_stop",
|
|
required=True, group_operator=False)
|
|
duration = fields.Float(string="Duration", required=True, group_operator=False)
|
|
datetime_start = fields.Datetime(string="Date start", compute="_get_datetimes", store=True)
|
|
datetime_stop = fields.Datetime(string="Date stop", compute="_get_datetimes", store=True)
|
|
count = fields.Integer(string="People count", required=True)
|
|
can_overlap = fields.Boolean(string="Table bookings can overlap")
|
|
available_table_ids = fields.Many2many(comodel_name='restaurant.table', string="Available tables",
|
|
column1="booking_id", column2="table_id", relation="booking_available_table_rel",
|
|
compute="_get_available_tables")
|
|
table_ids = fields.Many2many(comodel_name='restaurant.table', string="Tables", required=True,
|
|
column1="booking_id", column2="table_id", relation="booking_table_rel",
|
|
domain="[('id', 'in', available_table_ids)]")
|
|
table_capacity = fields.Integer(string="Capacity", compute="_get_table_capacity")
|
|
table_capacity_ok = fields.Boolean(string="Capacity OK", compute="_check_table_capacity")
|
|
table_booking_ids = fields.One2many(comodel_name="restaurant.table_booking", inverse_name="booking_id",
|
|
string="Tables bookings", readonly=True)
|
|
|
|
_sql_constraints = [
|
|
('start_time_check', 'CHECK(time_start >= 0 AND time_start <= 24)', "The start time must be between 0 and 24."),
|
|
('stop_time_check', 'CHECK(time_stop >= 0 AND time_stop <= 24)', "The stop time must be between 0 and 24."),
|
|
('times_order_check', 'CHECK(time_start < time_stop)', "The start time must be lower than the stop time."),
|
|
]
|
|
|
|
@api.depends('time_start', 'duration')
|
|
def _get_time_stop(self):
|
|
for booking in self:
|
|
if booking.time_start and booking.duration:
|
|
booking.time_stop = booking.time_start + booking.duration
|
|
else:
|
|
booking.time_stop = 0.0
|
|
|
|
@api.onchange('time_stop')
|
|
def _set_time_stop(self):
|
|
for booking in self:
|
|
stop = booking.time_stop
|
|
if stop:
|
|
booking.duration = stop - booking.time_start
|
|
|
|
@api.depends('date', 'time_start', 'time_stop')
|
|
def _get_datetimes(self):
|
|
user_tz = timezone(self.env.user.tz)
|
|
for booking in self:
|
|
date = booking.date
|
|
if date and booking.time_start:
|
|
dt_start = user_tz.localize(dtdatetime.combine(date, float2time(booking.time_start)))
|
|
booking.datetime_start = dt_start.astimezone(utc).replace(tzinfo=None)
|
|
else:
|
|
booking.datetime_start = False
|
|
if date and booking.time_stop:
|
|
dt_stop = user_tz.localize(dtdatetime.combine(date, float2time(booking.time_stop)))
|
|
booking.datetime_stop = dt_stop.astimezone(utc).replace(tzinfo=None)
|
|
else:
|
|
booking.datetime_stop = False
|
|
|
|
@api.depends('table_ids')
|
|
def _get_table_capacity(self):
|
|
for booking in self:
|
|
booking.table_capacity = sum(booking.table_ids.mapped('seats'))
|
|
|
|
@api.depends('table_capacity', 'count')
|
|
def _check_table_capacity(self):
|
|
for booking in self:
|
|
booking.table_capacity_ok = bool(booking.table_capacity >= booking.count)
|
|
|
|
@api.depends('datetime_start', 'datetime_stop', 'can_overlap')
|
|
def _get_available_tables(self):
|
|
Table = self.env['restaurant.table']
|
|
TableBooking = self.env['restaurant.table_booking']
|
|
for booking in self:
|
|
if booking.datetime_start and booking.datetime_stop:
|
|
domain = [('bookable', '=', True)]
|
|
if not self.can_overlap:
|
|
tbookings = TableBooking.search([
|
|
'|', '&', ('datetime_start', '<', booking.datetime_stop),
|
|
('datetime_start', '>=', booking.datetime_start),
|
|
'&', ('datetime_stop', '>', booking.datetime_start),
|
|
('datetime_stop', '<=', booking.datetime_stop)
|
|
])
|
|
domain.append(('id', 'not in', tbookings.mapped('table_id').ids))
|
|
booking.available_table_ids = Table.search(domain)
|
|
else:
|
|
booking.available_table_ids = [(5, 0, 0)]
|
|
|
|
# CRUD
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals_list):
|
|
for vals in vals_list:
|
|
vals.update({
|
|
'table_booking_ids': [(0, 0, {'table_id': table_id}) for table_id in vals['table_ids'][0][2]]
|
|
})
|
|
res = super().create(vals_list)
|
|
return res
|
|
|
|
def write(self, vals):
|
|
res = super().write(vals)
|
|
TableBooking = self.env['restaurant.table_booking']
|
|
to_unlink = TableBooking
|
|
for booking in self:
|
|
tables = booking.table_ids
|
|
table_bookings = booking.table_booking_ids
|
|
delete = table_bookings.filtered(lambda rtb: rtb.table_id not in tables)
|
|
to_unlink |= delete
|
|
to_create = tables - (table_bookings - delete).mapped('table_id')
|
|
if to_create:
|
|
TableBooking.create([{
|
|
'booking_id': booking.id,
|
|
'table_id': table.id,
|
|
} for table in to_create])
|
|
if to_unlink:
|
|
to_unlink.unlink()
|
|
return res
|