[IMP] point_of_sale, pos_*: overall improvements and fixes

List of improvements:
- Add `Is a Kiosk` field when creating a new POS config
- Add category and change the image of the combo demo product
- Hide useless settings when kiosk mode is enabled

List of fixes:
- Fix bootstrap carousel traceback when no image is set
- Changed the warning sentence concerning adyen payments
- Fix start category in kiosk
- Fix sync between Self Order mobile and PoS restaurant, now new Lines
  from restaurant are added to the mobile order
- Fix product reminder when adding something in PoS mobile

closes odoo/odoo#134508

Signed-off-by: Robin Heinz (rhe) <rhe@odoo.com>
This commit is contained in:
David Monnom (moda)
2023-09-08 07:17:52 +00:00
parent be3794ad72
commit 4a12c68184
17 changed files with 67 additions and 22 deletions
@@ -467,8 +467,9 @@
<field name="pos_categ_ids" eval="[(6, 0, [ref('pos_category_desks')])]"/>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="image_1920" type="base64" file="point_of_sale/static/img/office_combo.png"/>
<field name="image_1920" type="base64" file="point_of_sale/static/img/office_combo.jpg"/>
<field name="combo_ids" eval="[(6, 0, [ref('desks_combo'), ref('chairs_combo'), ref('desk_accessories_combo')])]"/>
<field name="pos_categ_ids" eval="[(6, 0, [ref('pos_category_miscellaneous')])]"/>
<field name="taxes_id" eval="[(5,)]"/> <!-- no taxes -->
</record>
@@ -888,7 +888,7 @@
<record id="chairs_combo" model="pos.combo">
<field name="name">Chairs Combo</field>
<field name="combo_line_ids" eval="[(6, 0, [ref('product_11_combo_line'), ref('product_11b_combo_line'), ref('product_12_combo_line')])]"/>
</record>
</record>
<record id="office_combo" model="product.product">
<field name="available_in_pos">True</field>
@@ -898,7 +898,7 @@
<field name="categ_id" ref="product.product_category_1"/>
<field name="uom_id" ref="uom.product_uom_unit"/>
<field name="uom_po_id" ref="uom.product_uom_unit"/>
<field name="image_1920" type="base64" file="point_of_sale/static/img/office_combo.png"/>
<field name="image_1920" type="base64" file="point_of_sale/static/img/office_combo.jpg"/>
<field name="combo_ids" eval="[(6, 0, [ref('desks_combo'), ref('chairs_combo'), ref('desk_accessories_combo')])]"/>
<field name="taxes_id" eval="[(5,)]"/> <!-- no taxes -->
<field name="pos_categ_ids" eval="[(6, 0, [ref('pos_category_miscellaneous')])]"/>
Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

@@ -363,6 +363,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
*/
get animationKey() {
return [
this.currentOrder.get_selected_orderline()?.uuid,
this.selectedOrderlineQuantity,
this.selectedOrderlineDisplayName,
this.selectedOrderlineTotal,
@@ -31,7 +31,7 @@
</div>
<!-- SHOW this div in create_mode (when '+ New Shop' is clicked in the general settings.) -->
<div class="row mt16 o_settings_container" invisible="not context.get('pos_config_create_mode', False)">
<div id="restaurant_on_create" class="row mt16 o_settings_container" invisible="not context.get('pos_config_create_mode', False)">
<setting>
<field name="module_pos_restaurant" />
</setting>
@@ -60,7 +60,7 @@
<setting string="Automatically validate order" help="Automatically validates orders paid with a payment terminal.">
<field name="pos_auto_validate_terminal_payment"/>
</setting>
<setting string="Cash Rounding" documentation="/applications/sales/point_of_sale/pricing/cash_rounding.html" help="Define the smallest coinage of the currency used to pay by cash">
<setting string="Cash Rounding" invisible="is_kiosk_mode" documentation="/applications/sales/point_of_sale/pricing/cash_rounding.html" help="Define the smallest coinage of the currency used to pay by cash">
<field name="pos_cash_rounding"/>
<div class="content-group mt16" invisible="not pos_cash_rounding">
<div class="row mt16">
@@ -128,13 +128,13 @@
<button name="%(product_pos_category_action)d" icon="oi-arrow-right" type="action" string="PoS Product Categories" class="btn-link"/>
</div>
</setting>
<setting help="Improve navigation for imprecise industrial touchscreens">
<setting invisible="is_kiosk_mode" help="Improve navigation for imprecise industrial touchscreens">
<field name="pos_iface_big_scrollbars"/>
</setting>
<setting id="margin_and_cost" string="Margins &amp; Costs" help="Show margins &amp; costs on product information">
<field name="pos_is_margins_costs_accessible_to_every_user"/>
</setting>
<setting string="Share Open Orders" help="Allow to access each other's active orders" id="is_order_shared" invisible="pos_module_pos_restaurant">
<setting string="Share Open Orders" help="Allow to access each other's active orders" id="is_order_shared" invisible="pos_module_pos_restaurant or is_kiosk_mode">
<div class="content-group">
<div class="row mt16">
<label string="Trusted POS" for="pos_trusted_config_ids" class="col-lg-3 o_light_label" />
+3 -2
View File
@@ -50,7 +50,7 @@ class PosSelfOrderController(http.Controller):
}
# Save the order in the database to get the id
posted_order_id = pos_config.env['pos.order'].create_from_ui([order], draft=True)[0].get('id')
posted_order_id = pos_config.env['pos.order'].with_context(from_self=True).create_from_ui([order], draft=True)[0].get('id')
# Process the lines and get their prices computed
lines = self._process_lines(lines, pos_config, posted_order_id, order.get('take_away'))
@@ -199,8 +199,9 @@ class PosSelfOrderController(http.Controller):
config_fiscal_pos = pos_config.default_fiscal_position_id
for line in lines:
if line.get('uuid') in appended_uuid:
if line.get('uuid') in appended_uuid or not line.get('product_id'):
continue
product = pos_config.env['product.product'].browse(int(line.get('product_id')))
# todo take into account the price extra
price_unit = pricelist._get_product_price(product, quantity=line.get('qty')) if pricelist else product.lst_price
+1 -1
View File
@@ -36,7 +36,7 @@ class PosConfig(models.Model):
)
self_order_kiosk_url = fields.Char(compute="_compute_self_order_kiosk_url")
self_order_kiosk = fields.Boolean(
string="Kiosk",
string="Is a Kiosk",
help="Enable the kiosk mode for the Point of Sale",
)
self_order_kiosk_takeaway = fields.Boolean(
+8 -1
View File
@@ -54,7 +54,10 @@ class PosOrder(models.Model):
def create_from_ui(self, orders, draft=False):
orders = super().create_from_ui(orders, draft)
order_ids = self.env['pos.order'].browse([order['id'] for order in orders])
self._send_notification(order_ids)
if self.env.context.get('from_self') is not True:
self._send_notification(order_ids)
return orders
@api.model
@@ -80,6 +83,10 @@ class PosOrder(models.Model):
'access_token': order.access_token,
'state': order.state
})
else:
self.env['bus.bus']._sendone(f'self_order-{order.access_token}', 'ORDER_CHANGED', {
'order': order._export_for_self_order()
})
def _export_for_self_order(self) -> Dict:
self.ensure_one()
@@ -103,12 +103,24 @@ export class Order extends Reactive {
}
}
const foundLines = [];
for (const lines of this.lines) {
const lineFound = data.lines.find((line) => line.uuid === lines.uuid);
if (lineFound) {
lines.updateDataFromServer(lineFound);
foundLines.push(lines);
}
}
for (const lines of data.lines) {
const lineFound = foundLines.find((line) => line.uuid === lines.uuid);
if (!lineFound) {
foundLines.push(new Line(lines));
}
}
this.lines = foundLines;
}
}
@@ -29,12 +29,15 @@ export class LandingPage extends Component {
});
onMounted(() => {
// used to init carousel after components mount / unmount
const carousel = new Carousel(this.carouselRef.el);
if (this.selfOrder.kiosk_image_home.length > 1) {
// used to init carousel after components mount / unmount
const carousel = new Carousel(this.carouselRef.el);
this.carouselInterval = setInterval(() => {
carousel.next();
}, 5000);
// prevent traceback when no image is set
this.carouselInterval = setInterval(() => {
carousel.next();
}, 5000);
}
});
onWillUnmount(() => {
@@ -31,8 +31,7 @@ export class selfOrder extends selfOrderCommon {
}
this.cookie.setCookie("frontend_lang", this.currentLanguage.code);
this.currentCategory = this.pos_category.length > 0 ? this.pos_category[0].name : null;
this.currentCategory = this.pos_category.length > 0 ? [...this.categoryList][0].name : null;
// required information to send an order
this.paymentError = false;
this.tablePadNumber = null;
@@ -37,12 +37,18 @@ export class SelfOrderBus {
dispatch(message) {
if (message.type === "ORDER_STATE_CHANGED") {
this.ws_changeOrderState(message.payload.access_token, message.payload.state);
} else if (message.type === "ORDER_CHANGED") {
this.ws_syncOrder(message.payload.order);
}
}
ws_changeOrderState(access_token, state) {
this.selfOrder.changeOrderState(access_token, state);
}
ws_syncOrder(order, state) {
this.selfOrder.updateOrdersFromServer([order], [order.access_token]);
}
}
export const SelfOrderBusService = {
@@ -155,13 +155,15 @@ export class SelfOrder extends selfOrderCommon {
}
}
updateOrdersFromServer(orders, localAccessToken) {
updateOrdersFromServer(ordersFromServer, localAccessToken) {
//FIXME, if the user refresh the page with not sent, we will lost this data.
const accessTokensFromServer = orders.map((order) => order.access_token);
const accessTokensFromServer = ordersFromServer.map((order) => order.access_token);
for (const order of this.orders) {
if (order.access_token) {
const orderFromServer = orders.find((o) => o.access_token === order.access_token);
const orderFromServer = ordersFromServer.find(
(o) => o.access_token === order.access_token
);
if (orderFromServer) {
order.updateDataFromServer(orderFromServer);
}
@@ -10,4 +10,17 @@
</xpath>
</field>
</record>
<record id="pos_self_config_view_form" model="ir.ui.view">
<field name="name">pos.config.form.view</field>
<field name="model">pos.config</field>
<field name="inherit_id" ref="point_of_sale.pos_config_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@id='restaurant_on_create']//setting" position="after">
<setting>
<field name="self_order_kiosk" />
</setting>
</xpath>
</field>
</record>
</odoo>
@@ -34,7 +34,7 @@
</block>
<xpath expr="//setting[@id='payment_methods_new']" position="before">
<div class="o_notification_alert alert alert-warning" role="alert" invisible="not is_kiosk_mode">
<span>Please note that only Adyen payment methods are supported by the kiosk.</span>
<span>Please note that the kiosk only works with Adyen terminals</span>
</div>
</xpath>
<block id="restaurant_section" position="after">