fix: resolve KDS stage reset bug by adding dependency and enforcing state closure after downstream overrides.
This commit is contained in:
parent
fe5a631a65
commit
4df8713787
@ -15,7 +15,7 @@ and todo status of previously processed prep order lines.
|
|||||||
'website': '',
|
'website': '',
|
||||||
'category': 'Sales/Point of Sale',
|
'category': 'Sales/Point of Sale',
|
||||||
'version': '19.0.1.0.0',
|
'version': '19.0.1.0.0',
|
||||||
'depends': ['pos_enterprise'],
|
'depends': ['pos_enterprise', 'custom_preparation_display'],
|
||||||
'data': [],
|
'data': [],
|
||||||
'assets': {},
|
'assets': {},
|
||||||
'installable': True,
|
'installable': True,
|
||||||
|
|||||||
@ -17,16 +17,26 @@ Problem:
|
|||||||
So the previously completed items (stage-advanced to last stage, todo=True) reappear
|
So the previously completed items (stage-advanced to last stage, todo=True) reappear
|
||||||
on the KDS card alongside the new item, effectively resetting their visual status.
|
on the KDS card alongside the new item, effectively resetting their visual status.
|
||||||
|
|
||||||
|
Additional complication:
|
||||||
|
The custom_preparation_display module ALSO overrides _process_preparation_changes
|
||||||
|
and runs AFTER pos_kds_fix in the MRO (since it calls super() which reaches here).
|
||||||
|
After super() returns, custom_preparation_display re-searches ALL prep orders
|
||||||
|
(including old ones) and syncs parent combo states. This can revert the todo=False
|
||||||
|
we set on old last-stage states back to todo=True, defeating the fix.
|
||||||
|
|
||||||
Fix:
|
Fix:
|
||||||
When a new pos.prep.order is created for an existing pos.order (meaning new items
|
1. Capture existing prep orders BEFORE super() creates a new one.
|
||||||
are being added to a table that already sent items to the kitchen), we find all
|
2. After all supers() have run (including custom_preparation_display's combo sync),
|
||||||
existing prep states for all PREVIOUS prep orders of the same pos.order that are
|
do a FINAL enforcement pass that forces all old last-stage states to todo=False.
|
||||||
currently at the LAST stage (regardless of todo status). These represent items
|
This runs last in the call chain so no subsequent override can undo it.
|
||||||
the kitchen staff already processed. We set their todo=False to ensure the filter
|
3. Only target states from genuinely OLD prep orders (pre-existing before this call).
|
||||||
in _get_open_orderlines_in_display() correctly excludes them from future reloads.
|
|
||||||
"""
|
"""
|
||||||
|
import logging
|
||||||
|
|
||||||
from odoo import models
|
from odoo import models
|
||||||
|
|
||||||
|
_logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class PosOrder(models.Model):
|
class PosOrder(models.Model):
|
||||||
_inherit = 'pos.order'
|
_inherit = 'pos.order'
|
||||||
@ -35,51 +45,78 @@ class PosOrder(models.Model):
|
|||||||
"""
|
"""
|
||||||
Override to fix KDS stage reset bug.
|
Override to fix KDS stage reset bug.
|
||||||
|
|
||||||
Before calling super(), we record existing prep orders for this pos.order.
|
We capture existing prep orders BEFORE super() (which may include
|
||||||
After super() runs (which may create a new prep order for new items),
|
custom_preparation_display's combo sync and pos_enterprise's core logic).
|
||||||
we mark all states in the OLD prep orders that are at the last stage
|
After the entire super() chain returns, we do a final enforcement pass
|
||||||
as todo=False so they won't reappear on the KDS display.
|
to ensure all old last-stage states remain todo=False regardless of
|
||||||
|
what any intermediate override may have set them to.
|
||||||
"""
|
"""
|
||||||
self.ensure_one()
|
self.ensure_one()
|
||||||
|
|
||||||
# Capture existing prep orders BEFORE super() creates a new one
|
# Step 1: Capture existing prep orders BEFORE super() creates a new one.
|
||||||
existing_prep_orders = self.env['pos.prep.order'].search([
|
# These are the "old" prep orders whose states should not be reset.
|
||||||
|
existing_prep_order_ids = self.env['pos.prep.order'].search([
|
||||||
('pos_order_id', '=', self.id)
|
('pos_order_id', '=', self.id)
|
||||||
])
|
]).ids
|
||||||
|
|
||||||
# Run the original logic (may create new pos.prep.order + lines + states)
|
# Step 2: Run the full super() chain.
|
||||||
|
# This includes:
|
||||||
|
# - custom_preparation_display._process_preparation_changes (combo sync)
|
||||||
|
# - pos_enterprise._process_preparation_changes (new prep order creation)
|
||||||
result = super()._process_preparation_changes(options)
|
result = super()._process_preparation_changes(options)
|
||||||
|
|
||||||
# If new items were added (flag_order_added), super() created a new prep order
|
# Step 3: Only act if new items were added (a new prep order was created).
|
||||||
if result.get('order_added') and existing_prep_orders:
|
if not result.get('order_added') or not existing_prep_order_ids:
|
||||||
# Fetch all prep displays relevant to this order
|
return result
|
||||||
prep_displays = self.env['pos.prep.display'].search([
|
|
||||||
'|',
|
# Step 4: Fetch all prep displays relevant to this order's POS config.
|
||||||
('pos_config_ids', '=', False),
|
prep_displays = self.env['pos.prep.display'].search([
|
||||||
('pos_config_ids', 'in', self.config_id.id),
|
'|',
|
||||||
|
('pos_config_ids', '=', False),
|
||||||
|
('pos_config_ids', 'in', self.config_id.id),
|
||||||
|
])
|
||||||
|
|
||||||
|
for prep_display in prep_displays:
|
||||||
|
stage_ids = prep_display.stage_ids.ids
|
||||||
|
if not stage_ids:
|
||||||
|
continue
|
||||||
|
last_stage_id = stage_ids[-1]
|
||||||
|
|
||||||
|
# Step 5: Find ALL states from OLD prep orders that are at the last stage.
|
||||||
|
# This covers both:
|
||||||
|
# (a) States with todo=True — kitchen staff used stage-advance button
|
||||||
|
# (b) States with todo=False — already correctly excluded by the filter
|
||||||
|
# but may have been re-set to True by custom_preparation_display's
|
||||||
|
# combo-parent sync logic.
|
||||||
|
# We unconditionally force them all to todo=False so the filter
|
||||||
|
# in _get_open_orderlines_in_display() correctly excludes them.
|
||||||
|
old_prep_lines = self.env['pos.prep.line'].search([
|
||||||
|
('prep_order_id', 'in', existing_prep_order_ids),
|
||||||
|
])
|
||||||
|
if not old_prep_lines:
|
||||||
|
continue
|
||||||
|
|
||||||
|
states_to_seal = self.env['pos.prep.state'].search([
|
||||||
|
('prep_line_id', 'in', old_prep_lines.ids),
|
||||||
|
('stage_id', '=', last_stage_id),
|
||||||
|
# Include both todo=True AND todo=False — if custom_preparation_display
|
||||||
|
# reverted a False back to True, we need to catch it.
|
||||||
|
# Using a simple search with no todo filter is intentional.
|
||||||
])
|
])
|
||||||
|
|
||||||
for prep_display in prep_displays:
|
# Separate the ones that still need updating to avoid unnecessary writes.
|
||||||
last_stage_id = (
|
states_needing_fix = states_to_seal.filtered(lambda s: s.todo)
|
||||||
prep_display.stage_ids.ids[-1]
|
if states_needing_fix:
|
||||||
if prep_display.stage_ids.ids else False
|
_logger.info(
|
||||||
|
"pos_kds_fix: Sealing %d old last-stage states as todo=False "
|
||||||
|
"for pos.order %s (prep orders: %s)",
|
||||||
|
len(states_needing_fix),
|
||||||
|
self.name or self.id,
|
||||||
|
existing_prep_order_ids,
|
||||||
)
|
)
|
||||||
if not last_stage_id:
|
# Use direct ORM write — no websocket notification is needed here.
|
||||||
continue
|
# The frontend will get a LOAD_ORDERS notification from process_order()
|
||||||
|
# anyway, and get_preparation_display_order() will re-read from DB.
|
||||||
# Find all states from the OLD prep orders that are at the last stage
|
states_needing_fix.write({'todo': False})
|
||||||
# with todo=True — these are items the kitchen advanced to "Completed"
|
|
||||||
# stage but which would still be returned by _get_open_orderlines_in_display
|
|
||||||
# because the filter only excludes (todo=False AND stage=last).
|
|
||||||
old_prep_lines = existing_prep_orders.mapped('prep_line_ids')
|
|
||||||
states_at_last_stage = self.env['pos.prep.state'].search([
|
|
||||||
('prep_line_id', 'in', old_prep_lines.ids),
|
|
||||||
('stage_id', '=', last_stage_id),
|
|
||||||
('todo', '=', True),
|
|
||||||
])
|
|
||||||
|
|
||||||
if states_at_last_stage:
|
|
||||||
# Mark them as done so the KDS filter hides them
|
|
||||||
states_at_last_stage.write({'todo': False})
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user