Odoo modules related to point of sales
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.

151 lines
6.5 KiB

4 years ago
  1. # -*- coding: utf-8 -*-
  2. from datetime import datetime as dtdatetime, time as dttime
  3. from odoo import models, fields, api
  4. from pytz import timezone, utc
  5. def float2time(fhours, seconds=False):
  6. hrs = int(fhours)
  7. fmin = (fhours - hrs) * 60
  8. min = int(fmin)
  9. sec = 0
  10. if seconds:
  11. fsec = (fmin - min) * 60
  12. sec = int(fsec)
  13. return dttime(hrs, min, sec)
  14. class RestaurantBooking(models.Model):
  15. _name = 'restaurant.booking'
  16. _description = "Restaurant booking"
  17. _order = 'date, time_start, count desc'
  18. @api.model
  19. def default_get(self, fields_list):
  20. defaults = super().default_get(fields_list)
  21. start = self.env.context.get('default_datetime_start', False)
  22. table_id = self.env.context.get('default_table_id', False)
  23. if start:
  24. defaults['date'] = start[:10]
  25. dtstart = fields.Datetime.context_timestamp(self, fields.Datetime.to_datetime(start))
  26. tstart = dtstart.hour
  27. if tstart:
  28. defaults['time_start'] = tstart
  29. if table_id:
  30. defaults['table_ids'] = [(6, 0, [table_id])]
  31. return defaults
  32. name = fields.Char(string="Name", required=True)
  33. date = fields.Date(string="Date", required=True)
  34. time_start = fields.Float(string="Start", required=True, group_operator=False)
  35. time_stop = fields.Float(string="Stop", compute="_get_time_stop", store=True, inverse="_set_time_stop",
  36. required=True, group_operator=False)
  37. duration = fields.Float(string="Duration", required=True, group_operator=False)
  38. datetime_start = fields.Datetime(string="Date start", compute="_get_datetimes", store=True)
  39. datetime_stop = fields.Datetime(string="Date stop", compute="_get_datetimes", store=True)
  40. count = fields.Integer(string="People count", required=True)
  41. available_table_ids = fields.Many2many(comodel_name='restaurant.table', string="Available tables",
  42. column1="booking_id", column2="table_id", relation="booking_available_table_rel",
  43. compute="_get_available_tables")
  44. table_ids = fields.Many2many(comodel_name='restaurant.table', string="Tables", required=True,
  45. column1="booking_id", column2="table_id", relation="booking_table_rel",
  46. domain="[('id', 'in', available_table_ids)]")
  47. table_capacity = fields.Integer(string="Capacity", compute="_get_table_capacity")
  48. table_capacity_ok = fields.Boolean(string="Capacity OK", compute="_check_table_capacity")
  49. table_booking_ids = fields.One2many(comodel_name="restaurant.table_booking", inverse_name="booking_id",
  50. string="Tables bookings", readonly=True)
  51. _sql_constraints = [
  52. ('start_time_check', 'CHECK(time_start >= 0 AND time_start <= 24)', "The start time must be between 0 and 24."),
  53. ('stop_time_check', 'CHECK(time_stop >= 0 AND time_stop <= 24)', "The stop time must be between 0 and 24."),
  54. ('times_order_check', 'CHECK(time_start < time_stop)', "The start time must be lower than the stop time."),
  55. ]
  56. @api.depends('time_start', 'duration')
  57. def _get_time_stop(self):
  58. for booking in self:
  59. if booking.time_start and booking.duration:
  60. booking.time_stop = booking.time_start + booking.duration
  61. else:
  62. booking.time_stop = 0.0
  63. @api.onchange('time_stop')
  64. def _set_time_stop(self):
  65. for booking in self:
  66. stop = booking.time_stop
  67. if stop:
  68. booking.duration = stop - booking.time_start
  69. @api.depends('date', 'time_start', 'time_stop')
  70. def _get_datetimes(self):
  71. user_tz = timezone(self.env.user.tz)
  72. for booking in self:
  73. date = booking.date
  74. if date and booking.time_start:
  75. dt_start = user_tz.localize(dtdatetime.combine(date, float2time(booking.time_start)))
  76. booking.datetime_start = dt_start.astimezone(utc).replace(tzinfo=None)
  77. else:
  78. booking.datetime_start = False
  79. if date and booking.time_stop:
  80. dt_stop = user_tz.localize(dtdatetime.combine(date, float2time(booking.time_stop)))
  81. booking.datetime_stop = dt_stop.astimezone(utc).replace(tzinfo=None)
  82. else:
  83. booking.datetime_stop = False
  84. @api.depends('table_ids')
  85. def _get_table_capacity(self):
  86. for booking in self:
  87. booking.table_capacity = sum(booking.table_ids.mapped('seats'))
  88. @api.depends('table_capacity', 'count')
  89. def _check_table_capacity(self):
  90. for booking in self:
  91. booking.table_capacity_ok = bool(booking.table_capacity >= booking.count)
  92. @api.depends('datetime_start', 'datetime_stop', 'table_ids')
  93. def _get_available_tables(self):
  94. Table = self.env['restaurant.table']
  95. TableBooking = self.env['restaurant.table_booking']
  96. for booking in self:
  97. if booking.datetime_start and booking.datetime_stop:
  98. tbookings = TableBooking.search([
  99. '|', '&', ('datetime_start', '<', booking.datetime_stop),
  100. ('datetime_start', '>=', booking.datetime_start),
  101. '&', ('datetime_stop', '>', booking.datetime_start),
  102. ('datetime_stop', '<=', booking.datetime_stop)
  103. ])
  104. booking.available_table_ids = Table.search([
  105. ('bookable', '=', True),
  106. ('id', 'not in', tbookings.mapped('table_id').ids),
  107. ]) - booking.table_ids
  108. else:
  109. booking.available_table_ids = [(5, 0, 0)]
  110. # CRUD
  111. @api.model_create_multi
  112. def create(self, vals_list):
  113. for vals in vals_list:
  114. vals.update({
  115. 'table_booking_ids': [(0, 0, {'table_id': table_id}) for table_id in vals['table_ids'][0][2]]
  116. })
  117. res = super().create(vals_list)
  118. return res
  119. def write(self, vals):
  120. res = super().write(vals)
  121. TableBooking = self.env['restaurant.table_booking']
  122. to_unlink = TableBooking
  123. for booking in self:
  124. tables = booking.table_ids
  125. table_bookings = booking.table_booking_ids
  126. delete = table_bookings.filtered(lambda rtb: rtb.table_id not in tables)
  127. to_unlink |= delete
  128. to_create = tables - (table_bookings - delete).mapped('table_id')
  129. if to_create:
  130. TableBooking.create([{
  131. 'booking_id': booking.id,
  132. 'table_id': table.id,
  133. } for table in to_create])
  134. if to_unlink:
  135. to_unlink.unlink()
  136. return res