From 0ae2b9a3f2d5af5ac8663f2b7960cb74fc53f119 Mon Sep 17 00:00:00 2001 From: "David Monnom (moda)" Date: Fri, 23 Jun 2023 10:17:24 +0000 Subject: [PATCH] [IMP] pos_self_order: change authorisation token Previously, access_token were linked to tables. These tables were linked to a floor_plan, which could be linked to several pos_configs. The only way to access the self-order was to obtain a valid table access_token. This behaviour was not correct because sometimes we would allow table selection directly in the interface or commands without a table. Now, access_token is managed by pos_config. When a user has this token, they can place commands and select the table they want if the option is enabled. closes odoo/odoo#126186 Signed-off-by: Joseph Caburnay (jcb) --- addons/pos_self_order/__manifest__.py | 3 +- addons/pos_self_order/controllers/entry.py | 48 ++++----- addons/pos_self_order/controllers/orders.py | 86 +++++++++------- addons/pos_self_order/controllers/utils.py | 28 +----- addons/pos_self_order/data/init_access.xml | 7 ++ .../data/restaurant_table_data.xml | 6 -- .../pos_self_order/demo/custom_link_data.xml | 10 -- addons/pos_self_order/models/pos_config.py | 47 ++++++--- .../pos_self_order/models/pos_restaurant.py | 36 +++---- .../src/components/popup_table/popup_table.js | 50 ++++++++++ .../components/popup_table/popup_table.scss | 15 +++ .../components/popup_table/popup_table.xml | 33 +++++++ .../components/product_card/product_card.js | 3 - .../components/product_card/product_card.xml | 4 +- .../src/pages/landing_page/landing_page.xml | 8 +- .../static/src/pages/order_cart/order_cart.js | 25 ++++- .../src/pages/order_cart/order_cart.xml | 1 + .../pages/orders_history/orders_history.js | 2 +- .../src/pages/product_list/product_list.xml | 2 +- .../product_main_view/product_main_view.xml | 4 +- .../static/src/self_order_router_service.js | 23 ++++- .../static/src/self_order_service.js | 98 ++++++++++--------- .../tours/self_order_after_meal_cart_tour.js | 6 ++ .../static/tests/tours/tour_utils.js | 16 ++- addons/pos_self_order/tests/__init__.py | 1 - .../pos_self_order/tests/test_controllers.py | 21 ---- addons/pos_self_order/tests/test_frontend.py | 1 + addons/pos_self_order/views/qr_code.xml | 3 - 28 files changed, 353 insertions(+), 234 deletions(-) create mode 100644 addons/pos_self_order/data/init_access.xml delete mode 100644 addons/pos_self_order/data/restaurant_table_data.xml delete mode 100644 addons/pos_self_order/demo/custom_link_data.xml create mode 100644 addons/pos_self_order/static/src/components/popup_table/popup_table.js create mode 100644 addons/pos_self_order/static/src/components/popup_table/popup_table.scss create mode 100644 addons/pos_self_order/static/src/components/popup_table/popup_table.xml delete mode 100644 addons/pos_self_order/tests/test_controllers.py diff --git a/addons/pos_self_order/__manifest__.py b/addons/pos_self_order/__manifest__.py index 7aaf2812e37..360902e0fdb 100644 --- a/addons/pos_self_order/__manifest__.py +++ b/addons/pos_self_order/__manifest__.py @@ -9,14 +9,13 @@ "auto_install": ["pos_restaurant"], "demo": [ "demo/pos_restaurant_demo.xml", - "demo/custom_link_data.xml", ], "data": [ "security/ir.model.access.csv", "views/index.xml", "views/qr_code.xml", "views/custom_link_views.xml", - "data/restaurant_table_data.xml", + "data/init_access.xml", "views/res_config_settings_views.xml", "views/point_of_sale_dashboard.xml", "data/pos_restaurant_data.xml", diff --git a/addons/pos_self_order/controllers/entry.py b/addons/pos_self_order/controllers/entry.py index a065183677d..4c103527d85 100644 --- a/addons/pos_self_order/controllers/entry.py +++ b/addons/pos_self_order/controllers/entry.py @@ -7,7 +7,6 @@ from odoo import http from odoo.http import request from odoo.addons.pos_self_order.controllers.utils import ( - get_pos_config_sudo, get_any_pos_config_sudo, get_table_sudo, ) @@ -23,39 +22,31 @@ class PosQRMenuController(http.Controller): to the server, using client side routing. """ - @http.route("/menu", auth="public") - def pos_self_order_redirect(self): - return request.redirect(f"/menu/{get_any_pos_config_sudo().id}") - @http.route( [ + "/menu/", "/menu/", "/menu//" ], - auth="public", - website=True, - sitemap=True, + auth="public", website=True, sitemap=True, ) - def pos_self_order_start(self, config_id: str, at=None): - """ - The user gets this route from the QR code that they scan at the table - :param config_id: the name of the pos config: can be the id or the slugified name of the pos config. (e.g. "3" or "bar-3") - :param at: the access token of the table; we call this argument "at" because - it will be displayed in the url ( as a query param ), and "at" is more user friendly than "access_token" - the user is allowed to order only if this "at" matches the access token of a table - :param product_id: the id of the product that the user wants to see the details of; - we never actually use this argument in this function ( it will be read by the client side router ), - but we still have it here, because otherwise we get a Warning in the logs - :return: the rendered template - """ - config_sudo = get_pos_config_sudo(config_id) - table_sudo = get_table_sudo(access_token=at) + def pos_self_order_start(self, config_id=None, access_token=None, table_identifier=None): + if config_id.isnumeric(): + pos_config_sudo = request.env["pos.config"].sudo().search([ + ("id", "=", config_id), + ('access_token', '=', access_token)], limit=1) + self_order_mode = 'qr_code' table_infos = False + pos_config_access_token = False - if config_sudo.has_active_session and config_sudo.self_order_table_mode and table_sudo: - table_infos = table_sudo._get_self_order_data() - self_order_mode = config_sudo.self_order_pay_after + if pos_config_sudo and pos_config_sudo.has_active_session and pos_config_sudo.self_order_table_mode: + self_order_mode = pos_config_sudo.self_order_pay_after + pos_config_access_token = pos_config_sudo.access_token + table_sudo = get_table_sudo(identifier=table_identifier) + table_infos = table_sudo._get_self_order_data() if table_sudo else False + else: + pos_config_sudo = get_any_pos_config_sudo() return request.render( 'pos_self_order.index', @@ -66,10 +57,11 @@ class PosQRMenuController(http.Controller): 'pos_self_order_data': { 'self_order_mode': self_order_mode, 'table': table_infos, - **config_sudo._get_self_order_data(), + 'access_token': pos_config_access_token, + **pos_config_sudo._get_self_order_data(), }, } - }, + } ) @http.route( @@ -109,7 +101,7 @@ class PosQRMenuController(http.Controller): :return: the bg image :rtype: binary """ - pos_config_sudo = get_pos_config_sudo(pos_config_id) + pos_config_sudo = request.env["pos.config"].sudo().browse(pos_config_id) if not pos_config_sudo.self_order_image: raise werkzeug.exceptions.NotFound() diff --git a/addons/pos_self_order/controllers/orders.py b/addons/pos_self_order/controllers/orders.py index 4303472ff52..e24f21ac94e 100644 --- a/addons/pos_self_order/controllers/orders.py +++ b/addons/pos_self_order/controllers/orders.py @@ -2,31 +2,17 @@ from datetime import timedelta import uuid - from odoo import http, fields, Command from odoo.http import request -from odoo.addons.pos_self_order.controllers.utils import ( - get_pos_config_sudo, - get_table_sudo, -) - from werkzeug.exceptions import NotFound, BadRequest, Unauthorized class PosSelfOrderController(http.Controller): @http.route("/pos-self-order/process-new-order", auth="public", type="json", website=True) - def process_new_order(self, order, table_access_token): - pos_config_id = order.get('pos_config_id') + def process_new_order(self, order, access_token, table_identifier): lines = order.get('lines') - pos_config_sudo = get_pos_config_sudo(pos_config_id) + pos_config_sudo, table_sudo = self._verify_authorization(access_token, table_identifier) pos_session_sudo = pos_config_sudo.current_session_id - table_sudo = get_table_sudo(table_access_token) - - if not pos_config_sudo.self_order_table_mode or not pos_config_sudo.has_active_session: - raise Unauthorized - if not table_sudo or not pos_session_sudo: - raise Unauthorized - sequence_number = self._get_sequence_number(table_sudo.id, pos_session_sudo.id) unique_id = self._generate_unique_id(pos_session_sudo.id, table_sudo.id, sequence_number) @@ -41,18 +27,18 @@ class PosSelfOrderController(http.Controller): 'sequence_number': sequence_number, 'access_token': uuid.uuid4().hex, 'pos_session_id': pos_session_sudo.id, - 'table_id': table_sudo.id, - "partner_id": False, - "creation_date": str(fields.Datetime.now()), - "fiscal_position_id": pos_config_sudo.default_fiscal_position_id, - "statement_ids": [], - "lines": [], + 'table_id': table_sudo.id if table_sudo else False, + 'partner_id': False, + 'creation_date': str(fields.Datetime.now()), + 'fiscal_position_id': pos_config_sudo.default_fiscal_position_id, + 'statement_ids': [], + 'lines': [], 'amount_tax': 0, 'amount_total': 0, 'amount_paid': 0, 'amount_return': 0, }, - "to_invoice": False, + 'to_invoice': False, 'session_id': pos_session_sudo.id, } @@ -76,11 +62,11 @@ class PosSelfOrderController(http.Controller): return order_sudo._export_for_self_order() @http.route('/pos-self-order/get-orders-taxes', auth='public', type='json', website=True) - def get_order_taxes(self, order, pos_config_id): - pos_config_sudo = get_pos_config_sudo(pos_config_id) + def get_order_taxes(self, order, access_token): + pos_config_sudo = request.env['pos.config'].sudo().search([('access_token', '=', access_token)], limit=1) - if not pos_config_sudo or not pos_config_sudo.self_order_table_mode: - raise Unauthorized + if not pos_config_sudo or not pos_config_sudo.self_order_table_mode or not pos_config_sudo.has_active_session: + raise Unauthorized("Invalid access token") lines = self._process_lines(order.get('lines'), pos_config_sudo, 0) amount_total, amount_untaxed = self._get_order_prices(lines) @@ -96,21 +82,21 @@ class PosSelfOrderController(http.Controller): } @http.route('/pos-self-order/update-existing-order', auth="public", type="json", website=True) - def update_existing_order(self, order): - order_pos_reference = order.get('pos_reference') + def update_existing_order(self, order, access_token, table_identifier): + order_id = order.get('id') order_access_token = order.get('access_token') - pos_config_id = order.get('pos_config_id') - pos_config_sudo = get_pos_config_sudo(pos_config_id) + pos_config_sudo, table_sudo = self._verify_authorization(access_token, table_identifier) order_sudo = request.env['pos.order'].sudo().search([ - ('pos_reference', '=', order_pos_reference), + ('id', '=', order_id), ('access_token', '=', order_access_token), + ('table_id', '=', table_sudo.id) ]) if not order_sudo: raise Unauthorized("Order not found in the server !") elif order_sudo.state != 'draft': - raise BadRequest("Order is not in draft state") + raise Unauthorized("Order is not in draft state") lines = self._process_lines(order.get('lines'), pos_config_sudo, order_sudo.id) for line in lines: @@ -135,14 +121,14 @@ class PosSelfOrderController(http.Controller): return order_sudo._export_for_self_order() @http.route('/pos-self-order/get-orders', auth='public', type='json', website=True) - def get_orders_by_access_token(self, access_tokens): + def get_orders_by_access_token(self, order_access_tokens): orders_sudo = request.env["pos.order"].sudo().search([ - ("access_token", "in", access_tokens), + ("access_token", "in", order_access_tokens), ("date_order", ">=", fields.Datetime.now() - timedelta(days=7)), ]) if not orders_sudo: - raise NotFound() + raise NotFound("Orders not found") orders = [] for order in orders_sudo: @@ -150,6 +136,20 @@ class PosSelfOrderController(http.Controller): return orders + @http.route('/pos-self-order/get-tables', auth='public', type='json', website=True) + def get_tables(self, access_token): + pos_config_sudo = request.env['pos.config'].sudo().search([('access_token', '=', access_token)], limit=1) + + if not pos_config_sudo or not pos_config_sudo.self_order_table_mode or not pos_config_sudo.has_active_session: + raise Unauthorized("Invalid access token") + + tables = pos_config_sudo.floor_ids.table_ids.filtered(lambda t: t.active).read(['id', 'name', 'identifier', 'floor_id']) + + for table in tables: + table['floor_name'] = table.get('floor_id')[1] + + return tables + def _process_lines(self, lines, pos_config_sudo, pos_order_id): newLines = [] pricelist = request.env['product.pricelist'].sudo().browse(pos_config_sudo.pricelist_id.id) @@ -204,10 +204,22 @@ class PosSelfOrderController(http.Controller): return f"Self-Order {first_part}-{second_part}-{third_part}" - def _get_sequence_number(self, table_id: int, session_id: int) -> int: + def _get_sequence_number(self, table_id, session_id): order_sudo = request.env["pos.order"].sudo().search([( 'pos_reference', 'like', f"Self-Order {session_id:0>5}-{table_id:0>3}")], order='id desc', limit=1) return (order_sudo.sequence_number + 1) or 1 + + def _verify_authorization(self, access_token, table_identifier): + table_sudo = request.env["restaurant.table"].sudo().search([('identifier', '=', table_identifier)], limit=1) + pos_config_sudo = request.env['pos.config'].sudo().search([('access_token', '=', access_token)], limit=1) + + if not pos_config_sudo or not pos_config_sudo.self_order_table_mode or not pos_config_sudo.has_active_session: + raise Unauthorized("Invalid access token") + + if not table_sudo: + raise Unauthorized("Table not found") + + return pos_config_sudo, table_sudo diff --git a/addons/pos_self_order/controllers/utils.py b/addons/pos_self_order/controllers/utils.py index 07e6296b096..223d93f4335 100644 --- a/addons/pos_self_order/controllers/utils.py +++ b/addons/pos_self_order/controllers/utils.py @@ -5,29 +5,7 @@ import werkzeug from typing import Optional from odoo.http import request -from odoo.addons.http_routing.models.ir_http import unslug from odoo.addons.pos_self_order.models.pos_config import PosConfig -from odoo.addons.pos_restaurant.models.pos_restaurant import RestaurantTable - - -def get_pos_config_sudo(pos_config_name: str) -> PosConfig: - """ - Returns the PosConfig if pos_config_id exist and the pos is configured to allow the menu to be viewed online. - If not, it raises a NotFound - :param pos_config_name: The name of the pos config. Can be the id or the slug. ex: 3 or Bar-3 - """ - return ( - request.env["pos.config"] - .sudo() - .search( - [ - ("id", "=", unslug(str(pos_config_name))[1]), - ("self_order_view_mode", "=", True), - ], - limit=1, - ) - ) or _raise(werkzeug.exceptions.NotFound()) - def get_any_pos_config_sudo() -> PosConfig: """ @@ -39,11 +17,11 @@ def get_any_pos_config_sudo() -> PosConfig: ) or _raise(werkzeug.exceptions.NotFound()) -def get_table_sudo(access_token: Optional[str]) -> Optional[RestaurantTable]: - return access_token and ( +def get_table_sudo(identifier): + return identifier and ( request.env["restaurant.table"] .sudo() - .search([("access_token", "=", access_token), ("active", "=", True)], limit=1) + .search([("identifier", "=", identifier), ("active", "=", True)], limit=1) ) diff --git a/addons/pos_self_order/data/init_access.xml b/addons/pos_self_order/data/init_access.xml new file mode 100644 index 00000000000..bb2237810dc --- /dev/null +++ b/addons/pos_self_order/data/init_access.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/addons/pos_self_order/data/restaurant_table_data.xml b/addons/pos_self_order/data/restaurant_table_data.xml deleted file mode 100644 index d7e6fe7b802..00000000000 --- a/addons/pos_self_order/data/restaurant_table_data.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/addons/pos_self_order/demo/custom_link_data.xml b/addons/pos_self_order/demo/custom_link_data.xml deleted file mode 100644 index e66ccc69535..00000000000 --- a/addons/pos_self_order/demo/custom_link_data.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - View Menu - - - - - diff --git a/addons/pos_self_order/models/pos_config.py b/addons/pos_self_order/models/pos_config.py index 5e384e62f2a..8d0fcc4a284 100644 --- a/addons/pos_self_order/models/pos_config.py +++ b/addons/pos_self_order/models/pos_config.py @@ -2,6 +2,7 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. from typing import Optional, List, Dict, Callable +import uuid from werkzeug.urls import url_quote import base64 @@ -10,7 +11,6 @@ from odoo import api, fields, models, modules from odoo.tools import file_open, split_every from odoo.addons.pos_self_order.models.product_product import ProductProduct -from odoo.addons.pos_self_order.models.pos_order import PosOrderLine class PosConfig(models.Model): @@ -52,6 +52,27 @@ class PosConfig(models.Model): help="Name of the image to display on the self order screen", default=_self_order_default_image_name, ) + access_token = fields.Char( + "Security Token", + copy=False, + required=True, + readonly=True, + default=lambda self: self._get_access_token(), + ) + + @staticmethod + def _get_access_token(): + return uuid.uuid4().hex[:16] + + def _update_access_token(self): + self.access_token = self._get_access_token() + self.floor_ids.table_ids._update_identifier() + + @api.model + def _init_access_token(self): + pos_config_ids = self.env["pos.config"].search([]) + for pos_config_id in pos_config_ids: + pos_config_id.access_token = self._get_access_token() @api.model_create_multi def create(self, vals_list): @@ -68,13 +89,6 @@ class PosConfig(models.Model): pos_config_id.self_order_view_mode = True pos_config_id.self_order_table_mode = True - self.env['pos_self_order.custom_link'].create({ - 'url': '/menu/%s/products' % pos_config_id.id, - 'name': 'View Menu', - 'pos_config_ids': pos_config_id, - 'style': 'primary', - }) - return pos_config_ids @api.depends("module_pos_restaurant") @@ -90,16 +104,19 @@ class PosConfig(models.Model): def _get_self_order_route(self, table_id: Optional[int] = None) -> str: self.ensure_one() base_route = f"/menu/{self.id}" + table_route = "" + if not self.self_order_table_mode: return base_route - access_token = ( - self.env["restaurant.table"] - .search( - [("active", "=", True), *(table_id and [("id", "=", table_id)] or [])], limit=1 - ) - .access_token + + table = self.env["restaurant.table"].search( + [("active", "=", True), ("id", "=", table_id)], limit=1 ) - return f"{base_route}?at={access_token}" + + if table: + table_route = f"&table_identifier={table.identifier}" + + return f"{base_route}?access_token={self.access_token}{table_route}" def _get_self_order_url(self, table_id: Optional[int] = None) -> str: self.ensure_one() diff --git a/addons/pos_self_order/models/pos_restaurant.py b/addons/pos_self_order/models/pos_restaurant.py index a3adcbe03b7..4efce62bb6c 100644 --- a/addons/pos_self_order/models/pos_restaurant.py +++ b/addons/pos_self_order/models/pos_restaurant.py @@ -23,45 +23,35 @@ class RestaurantFloor(models.Model): class RestaurantTable(models.Model): _inherit = "restaurant.table" - access_token = fields.Char( + identifier = fields.Char( "Security Token", copy=False, required=True, readonly=True, - default=lambda self: self._get_access_token(), + default=lambda self: self._get_identifier(), ) - @staticmethod - def _get_access_token(): - return uuid.uuid4().hex[:8] - def _get_self_order_data(self) -> Dict: self.ensure_one() - return self.read(["name", "access_token"])[0] + return self.read(["name", "identifier"])[0] def _get_data_for_qr_codes_page(self, url: Callable[[Optional[int]], str]) -> List[Dict]: return [ { - "access_token": table.access_token, - "id": table.id, - "name": table.name, - "url": url(table.id), + 'identifier': table.identifier, + 'id': table.id, + 'name': table.name, + 'url': url(table.id), } for table in self ] + @staticmethod + def _get_identifier(): + return uuid.uuid4().hex[:8] + @api.model - def _update_access_token(self): - """ - We define a new access token field in this file. - There might already be databases that have restaurant.table records. - They will now also get an access token each; the problem is that - because of the way `default` values work, all those tables that - exist in the db will get the same access token. - This method will be ran at the moment the pos_self_order module - is installed and will thus make sure that every record has a - different access token. - """ + def _update_identifier(self): tables = self.env["restaurant.table"].search([]) for table in tables: - table.access_token = self._get_access_token() + table.identifier = self._get_identifier() diff --git a/addons/pos_self_order/static/src/components/popup_table/popup_table.js b/addons/pos_self_order/static/src/components/popup_table/popup_table.js new file mode 100644 index 00000000000..976fa7d546c --- /dev/null +++ b/addons/pos_self_order/static/src/components/popup_table/popup_table.js @@ -0,0 +1,50 @@ +/** @odoo-module */ + +import { Component, onWillStart, useState } from "@odoo/owl"; +import { useSelfOrder } from "@pos_self_order/self_order_service"; +import { useService } from "@web/core/utils/hooks"; +import { groupBy } from "@web/core/utils/arrays"; + +export class PopupTable extends Component { + static template = "pos_self_order.PopupTable"; + static props = { selectTable: Function }; + + setup() { + this.selfOrder = useSelfOrder(); + this.router = useService("router"); + this.rpc = useService("rpc"); + this.tables = []; + this.state = useState({ + selectedTable: null, + }); + + onWillStart(async () => { + await this.getTable(); + }); + } + + async getTable() { + this.tables = await this.rpc("/pos-self-order/get-tables", { + access_token: this.selfOrder.access_token, + }); + this.state.selectedTable = this.tables[0]?.id; + } + + get availableFloor() { + const groupedFloors = groupBy(this.tables, (t) => t.floor_id[0]); + return Object.entries(groupedFloors).map(([floorId, tables]) => ({ + id: floorId, + name: tables[0].floor_id[1], + tables, + })); + } + + setTable() { + const table = this.tables.find((t) => t.id === parseInt(this.state.selectedTable)); + this.props.selectTable(table); + } + + close() { + this.props.selectTable(null); + } +} diff --git a/addons/pos_self_order/static/src/components/popup_table/popup_table.scss b/addons/pos_self_order/static/src/components/popup_table/popup_table.scss new file mode 100644 index 00000000000..50294c99ed0 --- /dev/null +++ b/addons/pos_self_order/static/src/components/popup_table/popup_table.scss @@ -0,0 +1,15 @@ +.o_self-popup-table { + border-radius: 35px 35px 0 0; + animation: popupAnimation 0.2s ease-in-out forwards; +} + +@keyframes popupAnimation { + 0% { + bottom: -40vh; + opacity: 1; + } + 100% { + bottom: 0; + opacity: 1; + } + } \ No newline at end of file diff --git a/addons/pos_self_order/static/src/components/popup_table/popup_table.xml b/addons/pos_self_order/static/src/components/popup_table/popup_table.xml new file mode 100644 index 00000000000..079487d8b95 --- /dev/null +++ b/addons/pos_self_order/static/src/components/popup_table/popup_table.xml @@ -0,0 +1,33 @@ + + + +
+
+
+
+

Confirm your table

+ to place the order +
+ +
+ + + Confirm + +
+ + diff --git a/addons/pos_self_order/static/src/components/product_card/product_card.js b/addons/pos_self_order/static/src/components/product_card/product_card.js index ad2b0a584d5..cb2a4aa770b 100644 --- a/addons/pos_self_order/static/src/components/product_card/product_card.js +++ b/addons/pos_self_order/static/src/components/product_card/product_card.js @@ -22,9 +22,6 @@ export class ProductCard extends Component { }, 0); } - // FIXME: we need to verify the product name for future attribute variants - // in case of variants, we need to show the main product screen with "add" btn - // if the user select the same variant as an existing orderline, we merge it. clickOnProduct() { const product = this.props.product; if (!this.canOpenProductMainView(product)) { diff --git a/addons/pos_self_order/static/src/components/product_card/product_card.xml b/addons/pos_self_order/static/src/components/product_card/product_card.xml index caef4d890e6..02602dcba9e 100644 --- a/addons/pos_self_order/static/src/components/product_card/product_card.xml +++ b/addons/pos_self_order/static/src/components/product_card/product_card.xml @@ -11,7 +11,7 @@
@@ -29,7 +29,7 @@ loading="lazy" onerror="this.remove()" /> - +
\ No newline at end of file diff --git a/addons/pos_self_order/static/src/pages/landing_page/landing_page.xml b/addons/pos_self_order/static/src/pages/landing_page/landing_page.xml index e561ac19341..865c7ce3053 100644 --- a/addons/pos_self_order/static/src/pages/landing_page/landing_page.xml +++ b/addons/pos_self_order/static/src/pages/landing_page/landing_page.xml @@ -15,7 +15,13 @@ - + + View Menu + +
{ this.selfOrder.getPricesFromServer(); @@ -25,15 +31,30 @@ export class OrderCart extends Component { return this.selfOrder.self_order_mode === "each" ? "Pay" : "Order"; } + async selectTable(table) { + if (table) { + this.selfOrder.table = table; + this.router.addTableIdentifier(table); + await this.processOrder(); + } + this.state.selectTable = false; + } + async processOrder() { if (this.sendInProgress) { return; } + if (!this.selfOrder.table) { + this.state.selectTable = true; + return; + } + if (this.selfOrder.self_order_mode === "meal") { this.sendInProgress = true; try { await this.selfOrder.sendDraftOrderToServer(); + this.router.navigate("default"); } finally { this.sendInProgress = false; } diff --git a/addons/pos_self_order/static/src/pages/order_cart/order_cart.xml b/addons/pos_self_order/static/src/pages/order_cart/order_cart.xml index 6cb804c5333..9d823779780 100644 --- a/addons/pos_self_order/static/src/pages/order_cart/order_cart.xml +++ b/addons/pos_self_order/static/src/pages/order_cart/order_cart.xml @@ -17,6 +17,7 @@ already sent
+
diff --git a/addons/pos_self_order/static/src/pages/orders_history/orders_history.js b/addons/pos_self_order/static/src/pages/orders_history/orders_history.js index 275ee229a50..19f812df301 100644 --- a/addons/pos_self_order/static/src/pages/orders_history/orders_history.js +++ b/addons/pos_self_order/static/src/pages/orders_history/orders_history.js @@ -32,7 +32,7 @@ export class OrdersHistory extends Component { } editOrder(order) { - if (this.selfOrder.self_order_mode === "meal" && order.state === "draft") { + if (order.state === "draft") { this.selfOrder.editedOrder = order; this.router.navigate("productList"); } else { diff --git a/addons/pos_self_order/static/src/pages/product_list/product_list.xml b/addons/pos_self_order/static/src/pages/product_list/product_list.xml index 34eb4a3b464..726bcab5043 100644 --- a/addons/pos_self_order/static/src/pages/product_list/product_list.xml +++ b/addons/pos_self_order/static/src/pages/product_list/product_list.xml @@ -70,7 +70,7 @@ but if there are no products (for example if you search for something that does not exist), the button would be at the top of the page ) --> -
+
-
+