147 lines
6.6 KiB
Python

from odoo import models, fields, api, _
import logging
_logger = logging.getLogger(__name__)
class PosOrderLine(models.Model):
_inherit = 'pos.order.line'
preparation_status = fields.Selection([
('waiting', 'Waiting'),
('preparing', 'Preparing'),
('ready', 'Ready'),
('served', 'Served'),
('cancelled', 'Cancelled')
], string='Preparation Status', default='waiting', tracking=True, group_expand='_read_group_preparation_status')
@api.model
def _read_group_preparation_status(self, stages, domain, order):
return ['waiting', 'preparing', 'ready', 'served']
color = fields.Integer(string='Color', default=0)
preparation_time_start = fields.Datetime(string='Start Time')
preparation_time_end = fields.Datetime(string='Ready Time')
cooking_time = fields.Integer(string='Cooking Time (min)', compute='_compute_cooking_time', store=True)
table_id = fields.Many2one('restaurant.table', related='order_id.table_id', string='Table', store=True)
floor_id = fields.Many2one('restaurant.floor', related='order_id.table_id.floor_id', string='Floor', store=True)
@api.depends('preparation_time_start', 'preparation_time_end')
def _compute_cooking_time(self):
for line in self:
if line.preparation_time_start and line.preparation_time_end:
diff = line.preparation_time_end - line.preparation_time_start
line.cooking_time = int(diff.total_seconds() / 60)
else:
line.cooking_time = 0
def _notify_pos(self):
"""Send notification to POS when order line status changes"""
_logger.info("=== _notify_pos called for %s lines ===" % len(self))
for line in self:
_logger.info(f"Processing line {line.id}, order: {line.order_id.name}, config: {line.order_id.config_id}")
if line.order_id.config_id:
channel_name = "pos_config_Channel_%s" % line.order_id.config_id.id
payload = {
'line_id': line.id,
'order_id': line.order_id.id,
'status': line.preparation_status,
'status_label': dict(self._fields['preparation_status']._description_selection(self.env)).get(line.preparation_status),
'order_uid': line.order_id.pos_reference,
'product_id': line.product_id.id,
'qty': line.qty,
}
_logger.info(f"KDS NOTIFICATION: Sending update for Line {line.id} Status {line.preparation_status} to {channel_name}")
self.env['bus.bus']._sendone(channel_name, 'kds_update', payload)
else:
_logger.warning(f"Line {line.id} has no config_id - cannot send notification")
def _notify_kds(self):
"""Send notification to KDS backend when new order lines are created"""
_logger.info("=== _notify_kds called for %s lines ===" % len(self))
for line in self:
# Only notify for kitchen items
if line.product_id.is_kitchen_item and line.product_id.name != 'Water':
# Send to global KDS channel
kds_channel = "kds_channel"
payload = {
'line_id': line.id,
'order_id': line.order_id.id,
'product_name': line.product_id.name,
'qty': line.qty,
'table_name': line.table_id.name if line.table_id else '',
'floor_name': line.floor_id.name if line.floor_id else '',
'customer_note': line.customer_note or '',
'preparation_status': line.preparation_status,
'create_date': line.create_date.isoformat() if line.create_date else '',
}
_logger.info(f"KDS BACKEND NOTIFICATION: New order line {line.id} for {line.product_id.name}")
self.env['bus.bus']._sendone(kds_channel, 'kds_new_order', payload)
@api.model_create_multi
def create(self, vals_list):
"""Override create to send notifications to KDS when new orders are added"""
lines = super(PosOrderLine, self).create(vals_list)
# Send notification to KDS backend only for new items (waiting status)
waiting_lines = lines.filtered(lambda l: l.preparation_status == 'waiting')
if waiting_lines:
waiting_lines._notify_kds()
return lines
def write(self, vals):
"""Prevent resetting 'served' or 'ready' status back to 'waiting' during POS sync"""
if 'preparation_status' in vals and vals['preparation_status'] == 'waiting':
for line in self:
if line.preparation_status in ['served', 'ready', 'preparing']:
# Keep the current status if it's already being processed or served
actual_vals = vals.copy()
actual_vals['preparation_status'] = line.preparation_status
super(PosOrderLine, line).write(actual_vals)
# Handle lines that are actually allowed to be updated to waiting
remaining_lines = self.filtered(lambda l: l.preparation_status not in ['served', 'ready', 'preparing'])
if remaining_lines:
res = super(PosOrderLine, remaining_lines).write(vals)
# If quantity changed or status is waiting, notify KDS to refresh
remaining_lines._notify_kds()
return res
return True
res = super(PosOrderLine, self).write(vals)
# Notify KDS for quantity changes on active items
if 'qty' in vals:
active_lines = self.filtered(lambda l: l.preparation_status in ['waiting', 'preparing'])
if active_lines:
active_lines._notify_kds()
return res
def action_start_preparing(self):
self.write({
'preparation_status': 'preparing',
'preparation_time_start': fields.Datetime.now()
})
self._notify_pos()
def action_mark_ready(self):
self.write({
'preparation_status': 'ready',
'preparation_time_end': fields.Datetime.now()
})
self._notify_pos()
def action_mark_served(self):
self.write({
'preparation_status': 'served'
})
self._notify_pos()
class PosOrder(models.Model):
_inherit = 'pos.order'
@api.model
def _prepare_order_line_vals(self, line, session_id=None):
res = super()._prepare_order_line_vals(line, session_id)
if 'preparation_status' in line:
res['preparation_status'] = line['preparation_status']
return res