154 lines
6.5 KiB
Python
154 lines
6.5 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from datetime import timedelta
|
|
|
|
from odoo.addons.point_of_sale.tests.common import TestPoSCommon
|
|
from odoo.tests import tagged
|
|
from odoo import Command, fields
|
|
|
|
|
|
@tagged('post_install', '-at_install')
|
|
class TestPosPreparationDisplay(TestPoSCommon):
|
|
|
|
@classmethod
|
|
def setUpClass(cls):
|
|
super().setUpClass()
|
|
cls.config = cls.basic_config
|
|
|
|
def test_load_preparation_display_model(self):
|
|
|
|
config1 = self.env['pos.config'].create({
|
|
'name': 'rest1',
|
|
'active': False
|
|
})
|
|
config2 = self.env['pos.config'].create({
|
|
'name': 'rest2'
|
|
})
|
|
config3 = self.env['pos.config'].create({
|
|
'name': 'rest3'
|
|
})
|
|
config4 = self.env['pos.config'].create({
|
|
'name': 'rest4'
|
|
})
|
|
|
|
# pos preperation display linked to specific configs
|
|
display1 = self.env['pos.prep.display'].create({
|
|
'name': 'Preparation Display 1',
|
|
'pos_config_ids': [Command.link(config1.id)]
|
|
})
|
|
display2 = self.env['pos.prep.display'].create({
|
|
'name': 'Preparation Display 2',
|
|
'pos_config_ids': [Command.link(config2.id)]
|
|
})
|
|
display3 = self.env['pos.prep.display'].create({
|
|
'name': 'Preparation Display 3',
|
|
'pos_config_ids': []
|
|
})
|
|
display4 = self.env['pos.prep.display'].create({
|
|
'name': 'Preparation Display 4',
|
|
'pos_config_ids': [Command.link(config3.id)]
|
|
})
|
|
|
|
config2.open_ui()
|
|
config3.open_ui()
|
|
config4.open_ui()
|
|
|
|
self.assertEqual({d['id'] for d in config2.current_session_id.load_data([])['pos.prep.display']},
|
|
{display1.id, display2.id, display3.id})
|
|
self.assertEqual({d['id'] for d in config3.current_session_id.load_data([])['pos.prep.display']},
|
|
{display1.id, display3.id, display4.id})
|
|
self.assertEqual({d['id'] for d in config4.current_session_id.load_data([])['pos.prep.display']},
|
|
{display1.id, display3.id})
|
|
|
|
def test_preparation_updated_on_stage_change(self):
|
|
prep_display = self.env['pos.prep.display'].create({
|
|
'name': 'Preparation Display 1',
|
|
'pos_config_ids': [Command.link(self.config.id)],
|
|
})
|
|
first_stage, second_stage, final_stage = prep_display.stage_ids
|
|
|
|
self.open_new_session()
|
|
order = next(iter(self._create_orders([{'pos_order_lines_ui_args': [(self.product, 1)]}]).values()))
|
|
order_line = order.lines[0]
|
|
# Simulate sending the order to preparation
|
|
self.env['pos.prep.order'].process_order(order.id)
|
|
|
|
prep_line = self.env['pos.prep.line'].search([('pos_order_line_id', '=', order_line.id)])
|
|
prep_state = self.env['pos.prep.state'].search([('prep_line_id', '=', prep_line.id)])
|
|
self.assertEqual(prep_state.stage_id, first_stage)
|
|
self.assertEqual(order_line.preparation_time, -1)
|
|
self.assertEqual(order_line.service_time, -1)
|
|
# Move order from first -> second stage
|
|
prep_state.change_state_stage(
|
|
{str(prep_state.id): second_stage.id},
|
|
prep_display.id,
|
|
)
|
|
self.assertEqual(prep_state.stage_id, second_stage)
|
|
self.assertNotEqual(order_line.preparation_time, -1)
|
|
self.assertEqual(order_line.service_time, -1)
|
|
# Move order from second -> final stage
|
|
prep_state.change_state_stage(
|
|
{str(prep_state.id): final_stage.id},
|
|
prep_display.id,
|
|
)
|
|
self.assertEqual(prep_state.stage_id, final_stage)
|
|
self.assertNotEqual(order_line.service_time, -1)
|
|
|
|
def _send_order_to_display(self, prep_display):
|
|
"""Open a session, sync one order routed to prep_display, return its pos.prep.order."""
|
|
self.open_new_session()
|
|
order = next(iter(self._create_orders([{'pos_order_lines_ui_args': [(self.product, 1)]}]).values()))
|
|
self.env['pos.prep.order'].process_order(order.id)
|
|
prep_line = self.env['pos.prep.line'].search([('pos_order_line_id', '=', order.lines[0].id)])
|
|
return prep_line.prep_order_id
|
|
|
|
def _screen_order_count(self, prep_display):
|
|
return len(prep_display.get_preparation_display_order(False)['pos.prep.order'])
|
|
|
|
def _badge_order_count(self, prep_display):
|
|
# order_count does not depend on the order records, invalidate manually
|
|
prep_display.invalidate_recordset(['order_count'])
|
|
return prep_display.order_count
|
|
|
|
def test_order_count_includes_orders_older_than_today(self):
|
|
"""An order that crossed midnight while still open must stay counted in
|
|
the kanban badge for as long as the preparation screen shows it."""
|
|
prep_display = self.env['pos.prep.display'].create({
|
|
'name': 'Kitchen Display',
|
|
'pos_config_ids': [Command.link(self.config.id)],
|
|
})
|
|
prep_order = self._send_order_to_display(prep_display)
|
|
|
|
self.assertEqual(self._screen_order_count(prep_display), 1)
|
|
self.assertEqual(self._badge_order_count(prep_display), 1)
|
|
|
|
# the session stays open past midnight
|
|
self.env.cr.execute(
|
|
"UPDATE pos_prep_order SET create_date = %s WHERE id = %s",
|
|
(fields.Datetime.now() - timedelta(days=1), prep_order.id),
|
|
)
|
|
prep_order.invalidate_recordset(['create_date'])
|
|
|
|
self.assertEqual(self._screen_order_count(prep_display), 1,
|
|
"the order is still displayed on the preparation screen")
|
|
self.assertEqual(self._badge_order_count(prep_display), 1,
|
|
"an order still shown on the screen must still be counted in the badge")
|
|
|
|
def test_order_count_cleared_by_reset(self):
|
|
"""Resetting the display clears the screen, so it must clear the badge too."""
|
|
prep_display = self.env['pos.prep.display'].create({
|
|
'name': 'Kitchen Display',
|
|
'pos_config_ids': [Command.link(self.config.id)],
|
|
})
|
|
self._send_order_to_display(prep_display)
|
|
|
|
self.assertEqual(self._screen_order_count(prep_display), 1)
|
|
self.assertEqual(self._badge_order_count(prep_display), 1)
|
|
|
|
prep_display.reset()
|
|
|
|
self.assertEqual(self._screen_order_count(prep_display), 0,
|
|
"reset removes the order from the preparation screen")
|
|
self.assertEqual(self._badge_order_count(prep_display), 0,
|
|
"reset must leave no outstanding work in the badge either")
|