diff --git a/addons/point_of_sale/models/pos_session.py b/addons/point_of_sale/models/pos_session.py
index e20cf1285cc..6db8ed7a5b9 100644
--- a/addons/point_of_sale/models/pos_session.py
+++ b/addons/point_of_sale/models/pos_session.py
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
-
+import secrets
from collections import defaultdict
from datetime import timedelta
from itertools import groupby
@@ -33,6 +33,7 @@ class PosSession(models.Model):
required=True,
index=True)
name = fields.Char(string='Session ID', required=True, readonly=True, default='/')
+ access_token = fields.Char('Security Token', copy=False)
user_id = fields.Many2one(
'res.users', string='Opened By',
required=True,
@@ -1757,13 +1758,24 @@ class PosSession(models.Model):
return taxes
+ def _ensure_access_token(self):
+ # Code taken from addons/portal/models/portal_mixin.py
+ if not self.access_token:
+ # we use a `write` to force the cache clearing otherwise `return self.access_token` will return False
+ self.sudo().write({'access_token': secrets.token_hex(16)})
+ return self.access_token
+
+ def _get_bus_channel_name(self):
+ return f'pos_session-{self.id}-{self._ensure_access_token()}'
+
def _loader_params_pos_session(self):
+ self._ensure_access_token()
return {
'search_params': {
'domain': [('id', '=', self.id)],
'fields': [
'id', 'name', 'user_id', 'config_id', 'start_at', 'stop_at', 'sequence_number',
- 'payment_method_ids', 'state', 'update_stock_at_closing', 'cash_register_balance_start'
+ 'payment_method_ids', 'state', 'update_stock_at_closing', 'cash_register_balance_start', 'access_token'
],
},
}
diff --git a/addons/point_of_sale/static/src/app/bus/pos_bus_service.js b/addons/point_of_sale/static/src/app/bus/pos_bus_service.js
index 0f193dea67a..96117de305f 100644
--- a/addons/point_of_sale/static/src/app/bus/pos_bus_service.js
+++ b/addons/point_of_sale/static/src/app/bus/pos_bus_service.js
@@ -13,8 +13,7 @@ export class PosBus {
this.pos = pos;
this.orm = orm;
- // initialize bus_service and listen on pos_config-`id` channel
- bus_service.addChannel(`pos_config-${pos.config.id}`);
+ bus_service.addChannel(`pos_session-${pos.pos_session.id}-${pos.pos_session.access_token}`);
bus_service.addEventListener("notification", ({ detail }) => {
for (const message of detail) {
this.dispatch(message);
diff --git a/addons/pos_restaurant/models/pos_config.py b/addons/pos_restaurant/models/pos_config.py
index a9a47d70170..6c7d39cc277 100644
--- a/addons/pos_restaurant/models/pos_config.py
+++ b/addons/pos_restaurant/models/pos_config.py
@@ -15,6 +15,7 @@ class PosConfig(models.Model):
floor_ids = fields.Many2many('restaurant.floor', string='Restaurant Floors', help='The restaurant floors served by this point of sale.')
set_tip_after_payment = fields.Boolean('Set Tip After Payment', help="Adjust the amount authorized by payment terminals to add a tip after the customers left or at the end of the day.")
module_pos_restaurant = fields.Boolean(default=True)
+ module_pos_restaurant_appointment = fields.Boolean("Table Booking")
def get_tables_order_count_and_printing_changes(self):
self.ensure_one()
diff --git a/addons/pos_restaurant/models/pos_order.py b/addons/pos_restaurant/models/pos_order.py
index 52c29c32bf2..372acd8af2f 100644
--- a/addons/pos_restaurant/models/pos_order.py
+++ b/addons/pos_restaurant/models/pos_order.py
@@ -71,8 +71,11 @@ class PosOrder(models.Model):
def send_table_count_notification(self, table_ids):
messages = []
for config in self.env['pos.config'].search([('floor_ids', 'in', table_ids.floor_id.ids)]):
- order_count = config.get_tables_order_count_and_printing_changes()
- messages.append((f'pos_config-{config.id}', 'TABLE_ORDER_COUNT', order_count))
+ config_cur_session = config.current_session_id
+
+ if config_cur_session:
+ order_count = config.get_tables_order_count_and_printing_changes()
+ messages.append((config_cur_session._get_bus_channel_name(), 'TABLE_ORDER_COUNT', order_count))
self.env['bus.bus']._sendmany(messages)
@api.model
diff --git a/addons/pos_restaurant/models/pos_restaurant.py b/addons/pos_restaurant/models/pos_restaurant.py
index 7fdcd699c31..d80d678aee5 100644
--- a/addons/pos_restaurant/models/pos_restaurant.py
+++ b/addons/pos_restaurant/models/pos_restaurant.py
@@ -85,31 +85,13 @@ class RestaurantTable(models.Model):
width = fields.Float('Width', default=50, help="The table's width in pixels")
height = fields.Float('Height', default=50, help="The table's height in pixels")
seats = fields.Integer('Seats', default=1, help="The default number of customer served at this table.")
- color = fields.Char('Color', help="The table's color, expressed as a valid 'background' CSS property value")
+ color = fields.Char('Color', help="The table's color, expressed as a valid 'background' CSS property value", default="#35D374")
active = fields.Boolean('Active', default=True, help='If false, the table is deactivated and will not be available in the point of sale')
def are_orders_still_in_draft(self):
draft_orders = self.env['pos.order'].search([('table_id', '=', self.id), ('state', '=', 'draft')])
return len(draft_orders) > 0
- @api.model
- def create_from_ui(self, table):
- """ create or modify a table from the point of sale UI.
- table contains the table's fields. If it contains an
- id, it will modify the existing table. It then
- returns the id of the table.
- """
- if table.get('floor_id'):
- table['floor_id'] = table['floor_id'][0]
-
- sanitized_table = dict([(key, val) for key, val in table.items() if key in self._fields and val is not None])
- table_id = sanitized_table.pop('id', False)
- if table_id:
- self.browse(table_id).write(sanitized_table)
- else:
- table_id = self.create(sanitized_table).id
- return table_id
-
@api.ondelete(at_uninstall=False)
def _unlink_except_active_pos_session(self):
confs = self.mapped('floor_id.pos_config_ids').filtered(lambda c: c.module_pos_restaurant)
diff --git a/addons/pos_restaurant/models/res_config_settings.py b/addons/pos_restaurant/models/res_config_settings.py
index 1fd35f799a2..13948d0e0b6 100644
--- a/addons/pos_restaurant/models/res_config_settings.py
+++ b/addons/pos_restaurant/models/res_config_settings.py
@@ -11,6 +11,7 @@ class ResConfigSettings(models.TransientModel):
pos_iface_printbill = fields.Boolean(compute='_compute_pos_module_pos_restaurant', store=True, readonly=False)
pos_iface_splitbill = fields.Boolean(compute='_compute_pos_module_pos_restaurant', store=True, readonly=False)
pos_set_tip_after_payment = fields.Boolean(compute='_compute_pos_set_tip_after_payment', store=True, readonly=False)
+ pos_module_pos_restaurant_appointment = fields.Boolean(related="pos_config_id.module_pos_restaurant_appointment", readonly=False)
@api.depends('pos_module_pos_restaurant', 'pos_config_id')
def _compute_pos_module_pos_restaurant(self):
diff --git a/addons/pos_restaurant/static/src/app/floor_screen/editable_table.xml b/addons/pos_restaurant/static/src/app/floor_screen/editable_table.xml
index 08fc5c0985e..09356ed0844 100644
--- a/addons/pos_restaurant/static/src/app/floor_screen/editable_table.xml
+++ b/addons/pos_restaurant/static/src/app/floor_screen/editable_table.xml
@@ -6,9 +6,6 @@
-
-
-
diff --git a/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.js b/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.js
index a656f24fcf1..e8181d735c3 100644
--- a/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.js
+++ b/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.js
@@ -44,7 +44,8 @@ export class FloorScreen extends Component {
isColorPicker: false,
});
const ui = useState(useService("ui"));
- this.pos.floorPlanStyle = ui.isSmall ? "kanban" : "default";
+ const mode = localStorage.getItem("floorPlanStyle");
+ this.pos.floorPlanStyle = ui.isSmall || mode == "kanban" ? "kanban" : "default";
this.floorMapRef = useRef("floor-map-ref");
this.addFloorRef = useRef("add-floor-ref");
this.map = useRef("map");
@@ -268,11 +269,26 @@ export class FloorScreen extends Component {
return firstNum.toString();
}
async _save(table) {
- const tableCopy = { ...table };
- delete tableCopy.floor;
- const tableId = await this.orm.call("restaurant.table", "create_from_ui", [tableCopy]);
- table.id = tableId;
- this.pos.tables_by_id[tableId] = table;
+ const tableCopy = {
+ floor_id: table.floor.id,
+ color: table.color,
+ height: table.height,
+ name: table.name,
+ position_h: table.position_h,
+ position_v: table.position_v,
+ seats: table.seats,
+ shape: table.shape,
+ width: table.width,
+ };
+
+ if (table.id) {
+ await this.orm.write("restaurant.table", [table.id], tableCopy);
+ } else {
+ const tableId = await this.orm.create("restaurant.table", [tableCopy]);
+
+ table.id = tableId[0];
+ this.pos.tables_by_id[tableId] = table;
+ }
}
async _renameFloor(floorId, newName) {
await this.orm.call("restaurant.floor", "rename_floor", [floorId, newName]);
@@ -359,7 +375,9 @@ export class FloorScreen extends Component {
}
}
async onSaveTable(table) {
- await this._save(table);
+ if (this.pos.tables_by_id[table.id]) {
+ await this._save(table);
+ }
}
async addFloor() {
const { confirmed, payload: newName } = await this.popup.add(TextInputPopup, {
@@ -381,6 +399,9 @@ export class FloorScreen extends Component {
}
async createTable() {
const newTable = await this._createTableHelper();
+ newTable.skip_changes = 0;
+ newTable.changes_count = 0;
+ newTable.order_count = 0;
if (newTable) {
this.state.selectedTableIds = [];
this.state.selectedTableIds.push(newTable.id);
@@ -564,9 +585,7 @@ export class FloorScreen extends Component {
}
}
this.pos.tables_by_id[id].active = false;
- await this.orm.call("restaurant.table", "create_from_ui", [
- { active: false, id: id },
- ]);
+ this.orm.write("restaurant.table", [id], { active: false });
this.activeFloor.tables = this.activeTables.filter((table) => table.id !== id);
delete this.pos.tables_by_id[id];
} else {
diff --git a/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.scss b/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.scss
index 06c75e23180..9791862e1c4 100644
--- a/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.scss
+++ b/addons/pos_restaurant/static/src/app/floor_screen/floor_screen.scss
@@ -150,40 +150,43 @@
// Should probably be moved to table.scss but currently the selectors are too generic
.table {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
position: absolute;
text-align: center;
- font-size: 18px;
color: white;
background: rgb(53, 211, 116);
border-radius: 3px;
cursor: pointer;
box-shadow: 0px 3px rgba(0,0,0,0.07);
transition: background-color 300ms ease-in-out;
- overflow: hidden;
+ box-sizing: border-box;
&.selected {
outline: solid rgba(255,255,255,0.3);
cursor: move;
z-index: 50;
+ overflow: hidden;
+ }
- .table-seats {
- margin-left: -12px;
- }
+ .infos {
+ display: flex;
+ gap: 1rem;
+ align-items: center;
+ justify-content: center;
}
.order-count {
- position: absolute;
- top: 0;
- left: 50%;
background: black;
- width: 20px;
- margin-top: 1px;
- margin-left: -10px;
- height: 20px;
- line-height: 20px;
- border-radius: 10px;
- font-size: 16px;
+ border-radius: 999px;
z-index: 10;
+ width: 16px;
+ height: 16px;
+ line-height: 16px;
+ font-size: 16px;
+ position: absolute;
+ padding: 3px;
&.notify-printing {
background: red;
@@ -195,37 +198,32 @@
}
}
- .table-cover {
- display: block;
- position: absolute;
- left: 0; right: 0; bottom: 0;
- border-radius: 0px 0px 3px 3px;
- background: rgba(0,0,0,0.2);
-
- &.full {
- border-radius: 3px 3px 3px 3px;
- }
- }
-
.table-seats {
- position: absolute;
display: inline-block;
- bottom: 0;
- left: 50%;
- height: 20px;
- line-height: 20px;
- font-size: 16px;
border-radius: 5px;
- margin-left: -16px;
- margin-bottom: 4px;
- background: black;
+ background: rgba(0,0,0,0.2);
color: white;
- opacity: 0.2;
z-index: 3;
- padding: 0 4px;
- }
- .table-seats-presence {
- opacity: 1;
+ overflow: hidden;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin: 0 auto;
+ padding: 0 10px;
+ position: absolute;
+ bottom: -5px;
+ left: 50%;
+ transform: translate(-50%, -50%);
+
+ .cover {
+ position: absolute;
+ left: 0;
+ top: 0;
+ height: 100%;
+ background: black;
+ opacity: 0.4;
+ z-index: -1;
+ }
}
.table-handle {
@@ -253,7 +251,6 @@
max-height: 100%;
overflow: hidden;
position: relative;
- bottom: 5px;
}
.edit-button.editing {
diff --git a/addons/pos_restaurant/static/src/app/floor_screen/table.js b/addons/pos_restaurant/static/src/app/floor_screen/table.js
index 92fb2b383d3..45a456b609f 100644
--- a/addons/pos_restaurant/static/src/app/floor_screen/table.js
+++ b/addons/pos_restaurant/static/src/app/floor_screen/table.js
@@ -1,6 +1,6 @@
/** @odoo-module */
-import { Component } from "@odoo/owl";
+import { Component, useState } from "@odoo/owl";
import { usePos } from "@point_of_sale/app/store/pos_hook";
export class Table extends Component {
@@ -25,26 +25,64 @@ export class Table extends Component {
setup() {
this.pos = usePos();
+ this.state = useState({
+ containerHeight: 0,
+ containerWidth: 0,
+ });
+ }
+ get fontSize() {
+ const size = this.state.containerHeight / 3;
+ return size > 20 ? 20 : size;
+ }
+ get badgeStyle() {
+ if (this.props.table.shape !== "round") {
+ return `top: -6px; right: -6px;`;
+ }
+
+ const tableHeight = this.state.containerHeight;
+ const tableWidth = this.state.containerWidth;
+ const radius = Math.min(tableWidth, tableHeight) / 2;
+
+ let left = 0;
+ let bottom = 0;
+
+ if (tableHeight > tableWidth) {
+ left = radius;
+ bottom = radius + (tableHeight - tableWidth);
+ } else {
+ bottom = radius;
+ left = radius + (tableWidth - tableHeight);
+ }
+
+ bottom += 0.7 * radius - 8;
+ left += 0.7 * radius - 8;
+
+ return `bottom: ${bottom}px; left: ${left}px;`;
}
get style() {
const table = this.props.table;
-
+ let style = "";
let background = table.color ? table.color : "rgb(53, 211, 116)";
let textColor = "white";
- let border = "auto";
- let boxShadow = "0px 3px rgba(0,0,0,0.07)";
+
if (!this.isOccupied()) {
- background = "transparent";
+ background = "#00000020";
const rgb = table.floor.background_color
.substring(4, table.floor.background_color.length - 1)
.replace(/ /g, "")
.split(",");
textColor =
(0.299 * rgb[0] + 0.587 * rgb[1] + 0.114 * rgb[2]) / 255 > 0.5 ? "black" : "white";
- border = "3px solid " + table.color;
- boxShadow = "none";
}
+ style += `
+ border: 3px solid ${table.color};
+ border-radius: ${table.shape === "round" ? 1000 : 3}px;
+ background: ${background};
+ box-shadow: 0px 3px rgba(0,0,0,0.07);
+ padding: ${table.shape === "round" ? "4px 10px" : "4px 8px"};
+ color: ${textColor};`;
+
if (this.pos.floorPlanStyle == "kanban") {
const floor = table.floor;
const index = floor.tables.indexOf(table);
@@ -54,37 +92,35 @@ export class Table extends Component {
const position_h =
widthTable * (index % nbrHorizontal) + 5 + (index % nbrHorizontal) * 10;
const position_v =
- widthTable * Math.floor(index / nbrHorizontal) +
- 5 +
+ (widthTable + 25) * Math.floor(index / nbrHorizontal) +
+ 10 +
Math.floor(index / nbrHorizontal) * 10;
- return `
+ this.state.containerHeight = widthTable;
+ this.state.containerWidth = widthTable;
+
+ style += `
width: ${widthTable}px;
height: ${widthTable}px;
- line-height: ${widthTable}px;
top: ${position_v}px;
left: ${position_h}px;
- border: ${border};
- border-radius: ${table.shape === "round" ? 1000 : 3}px;
- background: ${background};
- box-shadow: ${boxShadow};
- font-size: ${widthTable >= 150 ? 32 : 16}px;
- color: ${textColor};
`;
} else {
- return `
+ this.state.containerHeight = table.height;
+ this.state.containerWidth = table.width;
+
+ style += `
width: ${table.width}px;
height: ${table.height}px;
- line-height: ${table.height}px;
top: ${table.position_v}px;
left: ${table.position_h}px;
- border: ${border};
- border-radius: ${table.shape === "round" ? 1000 : 3}px;
- background: ${background};
- box-shadow: ${boxShadow};
- font-size: ${table.height >= 150 && table.width >= 150 ? 32 : 16}px;
- color: ${textColor};
`;
}
+
+ style += `
+ font-size: ${this.fontSize}px;
+ line-height: ${this.fontSize}px;`;
+
+ return style;
}
get fill() {
const customerCount = this.pos.getCustomerCount(this.props.table.id);
@@ -110,18 +146,16 @@ export class Table extends Component {
return !Number.isNaN(result) ? result : 0;
}
get orderCountClass() {
- const countClass = { "order-count": true };
- if (this.pos.orderPreparationCategories.size) {
- const notifications = this._getNotifications();
- countClass["notify-printing"] = notifications.printing;
- countClass["notify-skipped"] = notifications.skipped;
- }
+ const notifications = this._getNotifications();
+ const countClass = {
+ "order-count": true,
+ "notify-printing": notifications.printing,
+ "notify-skipped": notifications.skipped,
+ };
return countClass;
}
get customerCountDisplay() {
- return `${this.pos.getCustomerCount(this.props.table.id)}/${
- this.props.table.seats
- }`;
+ return `${this.pos.getCustomerCount(this.props.table.id)}/${this.props.table.seats}`;
}
_getNotifications() {
const table = this.props.table;
@@ -133,8 +167,7 @@ export class Table extends Component {
}
isOccupied() {
return (
- this.pos.getCustomerCount(this.props.table.id) > 0 ||
- this.props.table.order_count > 0
+ this.pos.getCustomerCount(this.props.table.id) > 0 || this.props.table.order_count > 0
);
}
}
diff --git a/addons/pos_restaurant/static/src/app/floor_screen/table.xml b/addons/pos_restaurant/static/src/app/floor_screen/table.xml
index 5e63a046402..5c9ad417313 100644
--- a/addons/pos_restaurant/static/src/app/floor_screen/table.xml
+++ b/addons/pos_restaurant/static/src/app/floor_screen/table.xml
@@ -1,19 +1,19 @@
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
diff --git a/addons/pos_restaurant/static/src/app/navbar/navbar.js b/addons/pos_restaurant/static/src/app/navbar/navbar.js
index ed3ca604966..f2902eb17a0 100644
--- a/addons/pos_restaurant/static/src/app/navbar/navbar.js
+++ b/addons/pos_restaurant/static/src/app/navbar/navbar.js
@@ -18,7 +18,9 @@ patch(Navbar.prototype, "pos_restaurant.Navbar", {
return this._super() || (this.pos.config.module_pos_restaurant && !this.pos.table);
},
onSwitchButtonClick() {
- this.pos.floorPlanStyle = this.pos.floorPlanStyle == "kanban" ? "default" : "kanban";
+ const mode = this.pos.floorPlanStyle == "kanban" ? "default" : "kanban";
+ localStorage.setItem("floorPlanStyle", mode);
+ this.pos.floorPlanStyle = mode;
},
toggleEditMode() {
this.pos.toggleEditMode();
diff --git a/addons/pos_restaurant/static/src/app/product_screen/order/order.js b/addons/pos_restaurant/static/src/app/product_screen/order/order.js
new file mode 100644
index 00000000000..72045bd34fc
--- /dev/null
+++ b/addons/pos_restaurant/static/src/app/product_screen/order/order.js
@@ -0,0 +1,44 @@
+/** @odoo-module */
+
+import { patch } from "@web/core/utils/patch";
+import { OrderWidget } from "@point_of_sale/app/screens/product_screen/order/order";
+import { AlertPopup } from "@point_of_sale/app/utils/alert_popup/alert_popup";
+import { _t } from "@web/core/l10n/translation";
+
+patch(OrderWidget.prototype, "pos_restaurant.OrderWidget", {
+ releaseTable() {
+ const currentTable = this.pos.table;
+ const orderOnTable = this.pos.orders.filter(
+ (o) => o.tableId === currentTable.id && o.finalized === false
+ );
+ const orderOnTableWithOrderline = orderOnTable.find((o) => o.orderlines.length > 0);
+
+ if (orderOnTableWithOrderline) {
+ this.popup.add(AlertPopup, {
+ title: _t("Open orders"),
+ body: _t(
+ "There are open orders on this table. Please close them before releasing the table."
+ ),
+ });
+
+ return;
+ }
+
+ for (const order of orderOnTable) {
+ this.pos.removeOrder(order);
+ }
+
+ this.pos.showScreen("FloorScreen");
+ },
+ get showReleaseBtn() {
+ if (!this.pos.config.module_pos_restaurant) {
+ return false;
+ }
+
+ const currentTable = this.pos.table;
+ const noEmptyOrderOnTable = this.pos.orders.filter(
+ (o) => o.tableId === currentTable.id && o.finalized === false && o.orderlines.length > 0
+ );
+ return noEmptyOrderOnTable.length ? false : true;
+ },
+});
diff --git a/addons/pos_restaurant/static/src/app/product_screen/order/order.xml b/addons/pos_restaurant/static/src/app/product_screen/order/order.xml
new file mode 100644
index 00000000000..51886bd73c5
--- /dev/null
+++ b/addons/pos_restaurant/static/src/app/product_screen/order/order.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
diff --git a/addons/pos_restaurant/static/src/js/Screens/ProductScreen/ControlButtons/TableGuestsButton.js b/addons/pos_restaurant/static/src/js/Screens/ProductScreen/ControlButtons/TableGuestsButton.js
index b7ec6918641..77287371e25 100644
--- a/addons/pos_restaurant/static/src/js/Screens/ProductScreen/ControlButtons/TableGuestsButton.js
+++ b/addons/pos_restaurant/static/src/js/Screens/ProductScreen/ControlButtons/TableGuestsButton.js
@@ -30,7 +30,7 @@ export class TableGuestsButton extends Component {
});
if (confirmed) {
- const guestCount = parseInt(inputNumber, 10) || 1;
+ const guestCount = parseInt(inputNumber, 10) || 0;
// Set the maximum number possible for an integer
const max_capacity = 2 ** 31 - 1;
if (guestCount > max_capacity) {
@@ -43,6 +43,12 @@ export class TableGuestsButton extends Component {
});
return;
}
+
+ if (guestCount == 0 && this.currentOrder.orderlines.length === 0) {
+ this.pos.removeOrder(this.currentOrder);
+ this.pos.showScreen("FloorScreen");
+ }
+
this.currentOrder.setCustomerCount(guestCount);
}
}
diff --git a/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js b/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js
index 8d5ac27076a..d77737bc21d 100644
--- a/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js
+++ b/addons/pos_restaurant/static/src/js/Screens/TicketScreen.js
@@ -16,8 +16,16 @@ patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", {
});
},
getTable(order) {
- if (order.getTable()) {
- return `${order.getTable().floor.name} (${order.getTable().name})`;
+ const table = order.getTable();
+ if (table) {
+ let floorAndTable = "";
+
+ if (this.pos.floors && this.pos.floors.length > 1) {
+ floorAndTable = `${table.floor.name}/`;
+ }
+
+ floorAndTable += table.name;
+ return floorAndTable;
}
},
//@override
@@ -118,9 +126,7 @@ patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", {
async onDoRefund() {
const order = this.getSelectedSyncedOrder();
if (this.pos.config.module_pos_restaurant && order && !this.pos.table) {
- this.pos.setTable(
- order.table ? order.table : Object.values(this.pos.tables_by_id)[0]
- );
+ this.pos.setTable(order.table ? order.table : Object.values(this.pos.tables_by_id)[0]);
}
this._super(...arguments);
},
diff --git a/addons/pos_restaurant/static/src/xml/Screens/ProductScreen/ControlButtons/TableGuestsButton.xml b/addons/pos_restaurant/static/src/xml/Screens/ProductScreen/ControlButtons/TableGuestsButton.xml
index dcf41ea658f..02a465be892 100644
--- a/addons/pos_restaurant/static/src/xml/Screens/ProductScreen/ControlButtons/TableGuestsButton.xml
+++ b/addons/pos_restaurant/static/src/xml/Screens/ProductScreen/ControlButtons/TableGuestsButton.xml
@@ -7,7 +7,7 @@
- Guests
+ Dine-in Guests
diff --git a/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js b/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js
index 7a93f004d84..f1b932892cb 100644
--- a/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js
+++ b/addons/pos_restaurant/static/tests/tours/helpers/FloorScreenTourMethods.js
@@ -131,17 +131,25 @@ class Check {
}
tableSeatIs(table, val) {
return [
+ {
+ content: `Unselect table`,
+ trigger: `.floor-map`,
+ },
{
content: `number of seats in table '${table}' is '${val}'`,
- trigger: `.floor-map .table .label:contains("${table}") ~ .table-seats:contains("${val}")`,
+ trigger: `.floor-map .table .infos:has(.label:contains("${table}")) ~ .table-seats:contains("${val}")`,
run: function () {},
},
+ {
+ content: `click table '${table}'`,
+ trigger: `.floor-map .table .label:contains("${table}")`,
+ },
];
}
orderCountSyncedInTableIs(table, count) {
return [
{
- trigger: `.floor-map .table .order-count:contains("${count}") ~ .label:contains("${table}")`,
+ trigger: `.floor-map .table .label:contains("${table}") ~ .order-count:contains("${count}")`,
run: function () {},
},
];
diff --git a/addons/pos_restaurant/views/res_config_settings_views.xml b/addons/pos_restaurant/views/res_config_settings_views.xml
index 8994ec0e24c..603fe31b39f 100644
--- a/addons/pos_restaurant/views/res_config_settings_views.xml
+++ b/addons/pos_restaurant/views/res_config_settings_views.xml
@@ -28,6 +28,14 @@
+
+
+
+
+ Save this page and come back here to set up the feature.
+
+
+