pos_kds_report/models/pos_prep_state.py

181 lines
7.2 KiB
Python

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.write({'state': 'in_prep'})
order_report = KdsOrderReport.search([
('pos_order_id', '=', order_id),
('prep_display_id', '=', display_id)
], limit=1)
if order_report:
order_report.write({'state': 'in_prep'})
return
# --- Completed ---
prep_time = order_line.preparation_time
svc_time = order_line.service_time
# Fallback timing logic
if prep_time == -1:
if old_last_stage_change:
prep_time = int(compute_seconds_since(old_last_stage_change))
else:
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:
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
line_report = KdsLineReport.search([
('pos_order_line_id', '=', order_line.id),
('prep_display_id', '=', display_id)
], limit=1)
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(),
'state': 'done',
}
if line_report:
# Accumulate if it was already existing (e.g. from a previous completion before reset)
# Note: We only accumulate if the current session's time is valid.
new_prep = line_report.preparation_time + prep_time
new_svc = line_report.service_time + svc_time
new_comp = new_prep + new_svc
_logger.info("KDS Re-Completed (Accumulating): Order %s, Line %s: %ss + %ss = %ss",
order_name, order_line.product_id.name, line_report.completion_time, comp_time, new_comp)
line_report.write({
'preparation_time': new_prep,
'service_time': new_svc,
'completion_time': new_comp,
'completion_datetime': vals['completion_datetime'],
'state': 'done',
})
# Update local comp_time for order report update below
comp_time = new_comp
else:
_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)
KdsLineReport.create(vals)
# Update Order Report
order_report = KdsOrderReport.search([
('pos_order_id', '=', order_id),
('prep_display_id', '=', display_id)
], limit=1)
if order_report:
# Update state and accumulate/max time
# We use the max completion time across all lines of this order for this display.
# If we just updated a line to 219s, and order report was 204s, it becomes 219s.
if comp_time > order_report.completion_time or order_report.state != 'done':
order_report.write({
'completion_time': max(comp_time, order_report.completion_time),
'state': 'done',
'completion_datetime': vals['completion_datetime'],
})
else:
KdsOrderReport.create({
'pos_order_id': order_id,
'prep_display_id': display_id,
'preparation_time': prep_time, # Simplified: will be updated by other lines if needed
'service_time': svc_time,
'completion_time': comp_time,
'state': 'done',
'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)