[FIX] pos_restaurant: synchronize orders in TicketScreen

Before this commit: if more than one user work on a PoS restaurant, the
synced validated orders wouldn't remove from other user devices.

Steps to reproduce the issue:
1. Create a PoS resturant
2. Login to the PoS with two different browser
3. Create some orders with some products in one of the browsers
4. Complete the orders in another browser
=> Orders will not remove from the first browser

The solution is to retrieve the latest orders of every table when going to
the TicketScreen

opw-2925193

closes odoo/odoo#100353

Related: odoo/enterprise#32871
Signed-off-by: Trinh Jacky (trj) <trj@odoo.com>
This commit is contained in:
pedrambiria
2022-10-21 15:19:13 +02:00
committed by Jacky (trj)
parent e2232c8909
commit 192b212123
6 changed files with 52 additions and 13 deletions
+2 -2
View File
@@ -13,8 +13,8 @@ class PosOrder(models.Model):
return fields
@api.model
def get_table_draft_orders(self, table_id):
table_orders = super().get_table_draft_orders(table_id)
def get_table_draft_orders(self, table_ids):
table_orders = super().get_table_draft_orders(table_ids)
for order in table_orders:
if order['employee_id']:
order['employee_id'] = order['employee_id'][0] if order['employee_id'] else False
+2 -2
View File
@@ -149,7 +149,7 @@ class PosOrder(models.Model):
]
@api.model
def get_table_draft_orders(self, table_id):
def get_table_draft_orders(self, table_ids):
"""Generate an object of all draft orders for the given table.
Generate and return an JSON object with all draft orders for the given table, to send to the
@@ -160,7 +160,7 @@ class PosOrder(models.Model):
:returns: list -- list of dict representing the table orders
"""
table_orders = self.search_read(
domain=[('state', '=', 'draft'), ('table_id', '=', table_id)],
domain=[('state', '=', 'draft'), ('table_id', 'in', table_ids)],
fields=self._get_fields_for_draft_order())
self._get_order_lines(table_orders)
@@ -3,9 +3,35 @@ odoo.define('pos_restaurant.TicketButton', function (require) {
const TicketButton = require('point_of_sale.TicketButton');
const Registries = require('point_of_sale.Registries');
const { isConnectionError } = require('point_of_sale.utils');
const PosResTicketButton = (TicketButton) =>
class extends TicketButton {
async onClick() {
if (this.env.pos.config.iface_floorplan && !this.props.isTicketScreenShown && !this.env.pos.table) {
try {
this.env.pos.setLoadingOrderState(true);
await this.env.pos._syncAllOrdersFromServer();
} catch (error) {
if (isConnectionError(error)) {
await this.showPopup('OfflineErrorPopup', {
title: this.env._t('Offline'),
body: this.env._t('Due to a connection error, the orders are not synchronized.'),
});
} else {
this.showPopup('ErrorPopup', {
title: this.env._t('Unknown error'),
body: error.message,
});
}
} finally {
this.env.pos.setLoadingOrderState(false);
this.showScreen('TicketScreen');
}
} else {
super.onClick();
}
}
/**
* If no table is set to pos, which means the current main screen
* is floor screen, then the order count should be based on all the orders.
+20 -7
View File
@@ -105,13 +105,13 @@ const PosRestaurantPosGlobalState = (PosGlobalState) => class PosRestaurantPosGl
}
this.config.iface_printers = !!this.unwatched.printers.length;
}
async _getTableOrdersFromServer(tableId) {
async _getTableOrdersFromServer(tableIds) {
this.set_synch('connecting', 1);
try {
const orders = await this.env.services.rpc({
model: 'pos.order',
method: 'get_table_draft_orders',
args: [tableId],
args: [tableIds],
}, {
timeout: TIMEOUT,
shadow: true,
@@ -199,21 +199,31 @@ const PosRestaurantPosGlobalState = (PosGlobalState) => class PosRestaurantPosGl
*/
async _syncTableOrdersFromServer(tableId) {
await this._removeOrdersFromServer(); // in case we were offline and we deleted orders in the mean time
const ordersJsons = await this._getTableOrdersFromServer(tableId);
const ordersJsons = await this._getTableOrdersFromServer([tableId]);
const tableOrders = this.getTableOrders(tableId);
tableOrders.forEach(order => {
this._replaceOrders(tableOrders, ordersJsons);
}
async _syncAllOrdersFromServer() {
await this._removeOrdersFromServer(); // in case we were offline and we deleted orders in the mean time
const tableIds = [].concat(...this.floors.map(floor => floor.tables.map(table => table.id)));
const ordersJsons = await this._getTableOrdersFromServer(tableIds); // get all orders
await this._syncTableOrdersToServer(); // to prevent losing the transferred orders
const allOrders = [...this.get_order_list()];
this._replaceOrders(allOrders, ordersJsons);
}
_replaceOrders(ordersToReplace, newOrdersJsons) {
ordersToReplace.forEach(order => {
// We don't remove the validated orders because we still want to see them in the ticket screen.
// Orders in 'ReceiptScreen' or 'TipScreen' are validated orders.
if (order.server_id && !order.finalized && !this.transferredOrdersSet.has(order)){
this.removeOrder(order, false);
}
});
ordersJsons.forEach(json => {
newOrdersJsons.forEach(json => {
// Because of the offline feature, some draft orders fetched from the backend will appear
// to belong in different table, but in fact they are already moved.
const transferredOrder = [...this.transferredOrdersSet].find(order => order.uid === json.uid)
const isSameTable = transferredOrder && transferredOrder.tableId === tableId;
const isSameTable = transferredOrder && transferredOrder.tableId === json.tableId;
if (isSameTable) {
// this means we transferred back to the original table, we'll prioritize the server state
this.removeOrder(transferredOrder, false);
@@ -224,6 +234,9 @@ const PosRestaurantPosGlobalState = (PosGlobalState) => class PosRestaurantPosGl
}
});
}
setLoadingOrderState(bool) {
this.loadingOrderState = bool;
}
loadRestaurantFloor() {
// we do this in the front end due to the circular/recursive reference needed
// Ignore floorplan features if no floor specified.
@@ -8,7 +8,7 @@
</xpath>
<xpath expr="//div[hasclass('order-row')]//div[@name='delete']" position="before">
<div t-if="env.pos.config.iface_floorplan" class="col" name="table">
<t t-if="order.table">
<t t-if="order.tableId">
<div t-if="env.isMobile">Table</div>
<div><t t-esc="getTable(order)"></t></div>
</t>
@@ -56,7 +56,7 @@ odoo.define('pos_restaurant.tour.TipScreen', function (require) {
Chrome.do.backToFloor();
FloorScreen.check.orderCountSyncedInTableIs('T5', '1');
Chrome.do.clickTicketButton();
TicketScreen.check.nthRowContains('4', 'Tipping');
TicketScreen.check.nthRowContains('3', 'Tipping');
// Tip 20% on order1
TicketScreen.do.selectOrder('-0001');