import logging from odoo import models, fields, api from odoo.addons.pos_enterprise.utils.date_utils import compute_seconds_since _logger = logging.getLogger(__name__) class PosPreparationState(models.Model): _inherit = 'pos.prep.state' def _update_kds_report(self, pdis_state, old_last_stage_change=None): """ Synchronous KDS report update. Optimized to minimize database calls and avoid redundant aggregations. """ if not pdis_state.prep_line_id: return order_line = pdis_state.prep_line_id.pos_order_line_id if not order_line: return order = order_line.order_id stage = pdis_state.stage_id if not stage: return display = stage.prep_display_id if not display: return stage_ids = display.stage_ids.ids if not stage_ids: return first_stage_id = stage_ids[0] last_stage_id = stage_ids[-1] second_last_stage_id = stage_ids[-2] if len(stage_ids) > 1 else False # Determine if this is a completion or a reset is_completed = False if len(stage_ids) > 1: if stage.id == last_stage_id: is_completed = True elif second_last_stage_id and stage.id == second_last_stage_id and not pdis_state.todo: is_completed = True else: if not pdis_state.todo: is_completed = True is_reset = (stage.id == first_stage_id and pdis_state.todo) if not (is_completed or is_reset): return display_id = display.id order_id = order.id order_name = order.name or order.pos_reference or "Order" KdsLineReport = self.env['pos.kds.report.line'].sudo() KdsOrderReport = self.env['pos.kds.report.order'].sudo() try: if is_reset: _logger.info("KDS Reset: Order %s on display %s", order_name, display.name) line_report = KdsLineReport.search([ ('pos_order_line_id', '=', order_line.id), ('prep_display_id', '=', display_id) ], limit=1) if line_report: line_report.unlink() order_report = KdsOrderReport.search([ ('pos_order_id', '=', order_id), ('prep_display_id', '=', display_id) ], limit=1) if order_report: res = KdsLineReport._read_group( [('pos_order_id', '=', order_id), ('prep_display_id', '=', display_id)], aggregates=['completion_time:max'] ) max_comp_time = res[0][0] if res else 0 if max_comp_time == 0: order_report.unlink() else: order_report.write({'completion_time': max_comp_time}) return # --- Completed --- # Use a slightly larger epsilon for -1 check to be safe with float/int conversions if any prep_time = order_line.preparation_time svc_time = order_line.service_time # Fallback timing logic if prep_time == -1: if old_last_stage_change: # If we have the old timestamp, it means we spent time in the previous stage prep_time = int(compute_seconds_since(old_last_stage_change)) else: # Otherwise use the current stage entry time prep_time = int(compute_seconds_since(pdis_state.last_stage_change)) if svc_time == -1: if is_completed and stage.id == last_stage_id and old_last_stage_change: # If moving to last stage, service time is time spent in previous stage svc_time = int(compute_seconds_since(old_last_stage_change)) else: svc_time = 0 prep_time = max(0, prep_time) svc_time = max(0, svc_time) comp_time = prep_time + svc_time _logger.info("KDS Completed: Order %s, Line %s: Prep=%ss, Svc=%ss, Total=%ss", order_name, order_line.product_id.name, prep_time, svc_time, comp_time) vals = { 'pos_order_id': order_id, 'pos_order_line_id': order_line.id, 'product_id': order_line.product_id.id, 'prep_display_id': display_id, 'preparation_time': prep_time, 'service_time': svc_time, 'completion_time': comp_time, 'completion_datetime': fields.Datetime.now(), } line_report = KdsLineReport.search([ ('pos_order_line_id', '=', order_line.id), ('prep_display_id', '=', display_id) ], limit=1) if line_report: line_report.write(vals) else: KdsLineReport.create(vals) # Update Order Report - Optimized to avoid _read_group inside loops order_report = KdsOrderReport.search([ ('pos_order_id', '=', order_id), ('prep_display_id', '=', display_id) ], limit=1) if order_report: # Only update if the new completion time is greater, or if it's been some time if comp_time > order_report.completion_time: order_report.write({ 'completion_time': comp_time, 'completion_datetime': vals['completion_datetime'], }) else: KdsOrderReport.create({ 'pos_order_id': order_id, 'prep_display_id': display_id, 'completion_time': comp_time, 'completion_datetime': vals['completion_datetime'], }) except Exception as e: _logger.error("KDS reporting failed for order %s: %s", order_name, e, exc_info=True) def _record_status_change_prep_time(self, pdis_state): super()._record_status_change_prep_time(pdis_state) self._update_kds_report(pdis_state) def _record_stage_change_prep_time(self, pdis_state, old_last_stage_change, prep_order_completion_time): super()._record_stage_change_prep_time(pdis_state, old_last_stage_change, prep_order_completion_time) self._update_kds_report(pdis_state, old_last_stage_change=old_last_stage_change)