[IMP] pos_self_order, pos_online_payment_self_order: settings behavior
Previously, mobile self-order was not available when restaurant mode was deactivated. Now it's possible to activate self-order mode without the restaurant option activated. Self-order will then be forced to "pickup zone" mode and pay after "each order". --- Previously, when the self-order was closed, a popup indicating this appeared in full screen. Now, this popup has been replaced by a banner at the top of the screen, so that the self-order can still be used in read-only mode. --- Previously, when the kiosk was loaded and there was no product available in the pos_config, a traceback was raised. Now, when we are in this case, we display a message indicating to first add products in full screen. --- Fixed a traceback when trying to start the POS by clicking on the image of the landing page. The function start() had been removed. It is now restored. closes odoo/odoo#137671 Signed-off-by: Adrien Guilliams (adgu) <adgu@odoo.com>
This commit is contained in:
@@ -9,22 +9,22 @@ patch(CartPage.prototype, {
|
||||
return super.pay(...arguments);
|
||||
}
|
||||
|
||||
if (this.sendInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const order = this.selfOrder.currentOrder;
|
||||
const mode = this.selfOrder.config.self_ordering_pay_after;
|
||||
const isOnlinePayment = this.selfOrder.pos_payment_methods.find((p) => p.is_online_payment);
|
||||
const service = this.selfOrder.config.self_ordering_service_mode;
|
||||
const takeAway = this.selfOrder.currentOrder.take_away;
|
||||
|
||||
if (this.sendInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.selfOrder.table && service === "table" && !takeAway) {
|
||||
this.state.selectTable = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mode === "meal" && isOnlinePayment) {
|
||||
const order = this.selfOrder.currentOrder;
|
||||
if (!order) {
|
||||
this.selfOrder.notification.add(_t("The current order is invalid."), {
|
||||
type: "danger",
|
||||
@@ -39,17 +39,28 @@ patch(CartPage.prototype, {
|
||||
this.checkAndOpenPaymentPage(order);
|
||||
}
|
||||
} else if (mode === "each") {
|
||||
this.sendInProgress = true;
|
||||
const order = await this.selfOrder.sendDraftOrderToServer();
|
||||
this.sendInProgress = false;
|
||||
this.checkAndOpenPaymentPage(order);
|
||||
} else {
|
||||
return super.pay(...arguments);
|
||||
}
|
||||
},
|
||||
checkAndOpenPaymentPage(order) {
|
||||
async checkAndOpenPaymentPage(order) {
|
||||
const isOnlinePayment = this.selfOrder.pos_payment_methods.find((p) => p.is_online_payment);
|
||||
|
||||
if (order) {
|
||||
if (order.state === "draft") {
|
||||
if (!isOnlinePayment) {
|
||||
this.selfOrder.notification.add(
|
||||
_t("The current order cannot be paid (no online payment method)."),
|
||||
{ type: "danger" }
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!order.isSavedOnServer) {
|
||||
await this.selfOrder.sendDraftOrderToServer();
|
||||
}
|
||||
|
||||
this.selfOrder.openOnlinePaymentPage(order);
|
||||
} else {
|
||||
this.selfOrder.notification.add(
|
||||
|
||||
@@ -150,6 +150,9 @@ class PosConfig(models.Model):
|
||||
if vals.get('self_ordering_mode') == 'kiosk' or record.self_ordering_mode == 'kiosk':
|
||||
vals['self_ordering_pay_after'] = 'each'
|
||||
|
||||
if (not vals.get('module_pos_restaurant') and not record.module_pos_restaurant) and vals.get('self_ordering_mode') == 'mobile':
|
||||
vals['self_ordering_pay_after'] = 'each'
|
||||
|
||||
return super().write(vals)
|
||||
|
||||
@api.depends("module_pos_restaurant")
|
||||
@@ -175,7 +178,7 @@ class PosConfig(models.Model):
|
||||
self.ensure_one()
|
||||
|
||||
table_qr_code = []
|
||||
if self.self_ordering_mode == 'mobile':
|
||||
if self.self_ordering_mode == 'mobile' and self.module_pos_restaurant and self.self_ordering_service_mode == 'table':
|
||||
table_qr_code.extend([{
|
||||
'name': floor.name,
|
||||
'type': 'table',
|
||||
|
||||
@@ -16,13 +16,19 @@ class ProductTemplate(models.Model):
|
||||
default=True,
|
||||
)
|
||||
|
||||
@api.constrains('available_in_pos')
|
||||
def _check_combo_inclusions(self):
|
||||
super()._check_combo_inclusions()
|
||||
self.self_order_available = False
|
||||
@api.onchange('available_in_pos')
|
||||
def _on_change_available_in_pos(self):
|
||||
for record in self:
|
||||
if not record.available_in_pos:
|
||||
record.self_order_available = False
|
||||
|
||||
def write(self, vals_list):
|
||||
if 'available_in_pos' in vals_list:
|
||||
if not vals_list['available_in_pos']:
|
||||
vals_list['self_order_available'] = False
|
||||
|
||||
res = super().write(vals_list)
|
||||
|
||||
if 'self_order_available' in vals_list:
|
||||
for record in self:
|
||||
for product in record.product_variant_ids:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
from odoo.exceptions import UserError
|
||||
from odoo.exceptions import ValidationError
|
||||
from odoo.tools.misc import split_every
|
||||
from werkzeug.urls import url_unquote
|
||||
|
||||
@@ -28,7 +28,12 @@ class ResConfigSettings(models.TransientModel):
|
||||
user_id = self.pos_self_ordering_default_user_id
|
||||
|
||||
if not user_id.has_group("point_of_sale.group_pos_user") and not user_id.has_group("point_of_sale.group_pos_manager"):
|
||||
raise UserError(_("The user must be a POS user"))
|
||||
raise ValidationError(_("The user must be a POS user"))
|
||||
|
||||
@api.onchange("pos_self_ordering_service_mode")
|
||||
def _onchange_pos_self_order_service_mode(self):
|
||||
if self.pos_self_ordering_service_mode == 'counter':
|
||||
self.pos_self_ordering_pay_after = "each"
|
||||
|
||||
@api.onchange("pos_self_ordering_default_language_id", "pos_self_ordering_available_language_ids")
|
||||
def _onchange_pos_self_order_kiosk_default_language(self):
|
||||
@@ -37,45 +42,47 @@ class ResConfigSettings(models.TransientModel):
|
||||
if not self.pos_self_ordering_default_language_id and self.pos_self_ordering_available_language_ids:
|
||||
self.pos_self_ordering_default_language_id = self.pos_self_ordering_available_language_ids[0]
|
||||
|
||||
@api.onchange("pos_self_ordering_mode")
|
||||
@api.onchange("pos_self_ordering_mode", "pos_module_pos_restaurant")
|
||||
def _onchange_pos_self_order_kiosk(self):
|
||||
if self.pos_self_ordering_mode == 'kiosk':
|
||||
self.is_kiosk_mode = True
|
||||
self.pos_module_pos_restaurant = False
|
||||
self.pos_self_ordering_pay_after = "each"
|
||||
|
||||
elif self.pos_self_ordering_mode == 'mobile' and not self.pos_module_pos_restaurant:
|
||||
raise UserError(_("In Self-Order mode, you must have the Restaurant module"))
|
||||
else:
|
||||
self.is_kiosk_mode = False
|
||||
|
||||
@api.onchange("pos_self_ordering_pay_after", "pos_self_ordering_mode")
|
||||
def _onchange_service_and_ordering(self):
|
||||
if self.pos_self_ordering_pay_after == "meal" and self.pos_self_ordering_mode == 'mobile':
|
||||
self.pos_self_ordering_service_mode = 'table'
|
||||
if not self.pos_module_pos_restaurant:
|
||||
self.pos_self_ordering_service_mode = 'counter'
|
||||
|
||||
@api.onchange("pos_self_ordering_pay_after", "pos_self_ordering_mode")
|
||||
def _onchange_pos_self_order_pay_after(self):
|
||||
if self.pos_self_ordering_pay_after == "meal" and self.pos_self_ordering_mode == 'kiosk':
|
||||
raise UserError(_("Only pay after each is available with kiosk mode."))
|
||||
raise ValidationError(_("Only pay after each is available with kiosk mode."))
|
||||
|
||||
if self.pos_self_ordering_service_mode == 'counter' and self.pos_self_ordering_mode == 'mobile':
|
||||
self.pos_self_ordering_pay_after = "each"
|
||||
|
||||
if self.pos_self_ordering_pay_after == "each" and not self.module_pos_preparation_display:
|
||||
self.module_pos_preparation_display = True
|
||||
|
||||
@api.onchange("pos_self_ordering_service_mode")
|
||||
def _onchange_pos_self_ordering_service_mode(self):
|
||||
table_ids = self.pos_floor_ids.table_ids
|
||||
if self.pos_self_ordering_service_mode == 'table' and self.pos_self_ordering_mode == 'mobile' and not table_ids:
|
||||
raise UserError(_("In Self-Order mode, you must have at least one table to use the table service mode"))
|
||||
def custom_link_action(self):
|
||||
self.ensure_one()
|
||||
return {
|
||||
"type": "ir.actions.act_window",
|
||||
"res_model": "pos_self_order.custom_link",
|
||||
"views": [[False, "tree"]],
|
||||
"domain": [['pos_config_ids', 'in', self.pos_config_id.id]],
|
||||
}
|
||||
|
||||
def generate_qr_codes_page(self):
|
||||
"""
|
||||
Generate the data needed to print the QR codes page
|
||||
"""
|
||||
if self.pos_self_ordering_mode == 'mobile':
|
||||
if self.pos_self_ordering_mode == 'mobile' and self.pos_module_pos_restaurant:
|
||||
table_ids = self.pos_config_id.floor_ids.table_ids
|
||||
|
||||
if not table_ids:
|
||||
raise UserError(_("In Self-Order mode, you must have at least one table to generate QR codes"))
|
||||
raise ValidationError(_("In Self-Order mode, you must have at least one table to generate QR codes"))
|
||||
|
||||
url = url_unquote(self.pos_config_id._get_self_order_url(table_ids[0].id))
|
||||
name = table_ids[0].name
|
||||
@@ -94,7 +101,8 @@ class ResConfigSettings(models.TransientModel):
|
||||
}
|
||||
for floor in self.pos_config_id._get_qr_code_data()
|
||||
],
|
||||
'table_mode': self.pos_self_ordering_mode,
|
||||
'table_mode': self.pos_self_ordering_mode and self.pos_module_pos_restaurant and self.pos_self_ordering_service_mode == 'table',
|
||||
'self_order': self.pos_self_ordering_mode == 'mobile',
|
||||
'table_example': {
|
||||
'name': name,
|
||||
'decoded_url': url or "",
|
||||
|
||||
@@ -40,19 +40,20 @@ export class OrderWidget extends Component {
|
||||
const currentPage = this.router.activeSlot;
|
||||
const payAfter = this.selfOrder.config.self_ordering_pay_after;
|
||||
const kioskPayment = this.selfOrder.pos_payment_methods.find((p) => !p.is_online_payment); // cannot be online payment in kiosk for instance
|
||||
const isLine = this.selfOrder.currentOrder.lines.length !== 0;
|
||||
const isNoLine = this.selfOrder.currentOrder.lines.length === 0;
|
||||
|
||||
let label = "";
|
||||
let disabled = !isLine;
|
||||
let disabled = false;
|
||||
|
||||
if (currentPage === "product_list") {
|
||||
label = _t("Order");
|
||||
disabled = isNoLine;
|
||||
} else if (payAfter === "meal" && !this.selfOrder.currentOrder.isSavedOnServer) {
|
||||
label = _t("Order");
|
||||
disabled = disabled || !kioskPayment;
|
||||
disabled = isNoLine;
|
||||
} else {
|
||||
label = kioskPayment ? _t("Pay") : _t("Pay at cashier");
|
||||
disabled = disabled || kioskPayment;
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
return { label, disabled };
|
||||
|
||||
@@ -15,7 +15,7 @@ export class CartPage extends Component {
|
||||
setup() {
|
||||
this.selfOrder = useSelfOrder();
|
||||
this.router = useService("router");
|
||||
|
||||
this.sendInProgress = false;
|
||||
this.state = useState({
|
||||
selectTable: false,
|
||||
cancelConfirmation: false,
|
||||
@@ -49,6 +49,10 @@ export class CartPage extends Component {
|
||||
}
|
||||
|
||||
async pay() {
|
||||
if (this.sendInProgress) {
|
||||
return;
|
||||
}
|
||||
|
||||
const orderingMode = this.selfOrder.config.self_ordering_service_mode;
|
||||
const type = this.selfOrder.config.self_ordering_mode;
|
||||
const takeAway = this.selfOrder.currentOrder.take_away;
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Component } from "@odoo/owl";
|
||||
|
||||
export class ClosedPage extends Component {
|
||||
static template = "pos_self_order.ClosedPage";
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="pos_self_order.ClosedPage">
|
||||
<div class="d-flex gap-3 h-100 w-100 align-items-center justify-content-center text-bg-800">
|
||||
<span class="fs-1">The kiosk is closed</span>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
@@ -68,6 +68,10 @@ export class LandingPage extends Component {
|
||||
return;
|
||||
}
|
||||
|
||||
this.start();
|
||||
}
|
||||
|
||||
start() {
|
||||
if (
|
||||
this.selfOrder.config.self_ordering_takeaway &&
|
||||
this.selfOrder.currentOrder.take_away === null
|
||||
|
||||
@@ -23,24 +23,18 @@ export class PaymentPage extends Component {
|
||||
});
|
||||
|
||||
onWillStart(async () => {
|
||||
if (this.selfOrder.currentOrder.lines.length === 0) {
|
||||
this.router.navigate("default");
|
||||
return;
|
||||
}
|
||||
|
||||
const type = this.selfOrder.config.self_ordering_mode;
|
||||
const paymentMethods = this.selfOrder.pos_payment_methods.filter(
|
||||
(p) => !p.is_online_payment
|
||||
);
|
||||
|
||||
if (paymentMethods.length === 0 && type === "kiosk") {
|
||||
try {
|
||||
const order = await this.rpc("/pos-self-order/process-new-order/kiosk", {
|
||||
order: this.selfOrder.currentOrder,
|
||||
access_token: this.selfOrder.access_token,
|
||||
table_identifier: null,
|
||||
});
|
||||
|
||||
this.selfOrder.updateOrderFromServer(order);
|
||||
} catch (error) {
|
||||
this.selfOrder.handleErrorNotification(error);
|
||||
}
|
||||
|
||||
this.selfOrder.sendDraftOrderToServer();
|
||||
this.router.navigate("payment_success");
|
||||
} else if (paymentMethods.length === 1 && type === "kiosk") {
|
||||
this.selectMethod(this.selfOrder.pos_payment_methods[0].id);
|
||||
|
||||
@@ -74,13 +74,12 @@ export class SelfOrderBus {
|
||||
|
||||
if (payload.status === "closed") {
|
||||
this.selfOrder.pos_session = [];
|
||||
this.selfOrder.ordering = false;
|
||||
} else {
|
||||
// reload to get potential new settings
|
||||
// more easier than RPC for now
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
this.selfOrder.isSession();
|
||||
}
|
||||
|
||||
ws_productChanged(message) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/** @odoo-module */
|
||||
import { Component, whenReady, App, onMounted } from "@odoo/owl";
|
||||
import { Component, whenReady, App } from "@odoo/owl";
|
||||
import { makeEnv, startServices } from "@web/env";
|
||||
import { templates } from "@web/core/assets";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
@@ -15,7 +15,6 @@ import { PaymentPage } from "@pos_self_order/app/pages/payment_page/payment_page
|
||||
import { PaymentSuccessPage } from "@pos_self_order/app/pages/payment_success_page/payment_success_page";
|
||||
import { EatingLocationPage } from "@pos_self_order/app/pages/eating_location_page/eating_location_page";
|
||||
import { StandNumberPage } from "@pos_self_order/app/pages/stand_number_page/stand_number_page";
|
||||
import { ClosedPage } from "@pos_self_order/app/pages/closed_page/closed_page";
|
||||
import { OrdersHistoryPage } from "@pos_self_order/app/pages/order_history_page/order_history_page";
|
||||
|
||||
class selfOrderIndex extends Component {
|
||||
@@ -25,7 +24,6 @@ class selfOrderIndex extends Component {
|
||||
Router,
|
||||
CartPage,
|
||||
ProductPage,
|
||||
ClosedPage,
|
||||
OrdersHistoryPage,
|
||||
ComboPage,
|
||||
PaymentPage,
|
||||
@@ -39,10 +37,9 @@ class selfOrderIndex extends Component {
|
||||
|
||||
setup() {
|
||||
this.selfOrder = useSelfOrder();
|
||||
|
||||
onMounted(() => {
|
||||
this.selfOrder.isSession();
|
||||
});
|
||||
}
|
||||
get selfIsReady() {
|
||||
return Object.values(this.selfOrder.productByIds).length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="pos_self_order.selfOrderIndex">
|
||||
<Router pos_config_id="selfOrder.pos_config_id">
|
||||
<div t-if="!selfOrder.ordering" class="w-100 m-0 text-center bg-black text-white">
|
||||
<p>We're currently closed.</p>
|
||||
</div>
|
||||
<Router t-if="selfIsReady" pos_config_id="selfOrder.pos_config_id">
|
||||
<t t-set-slot="default" route="`/pos-self/${selfOrder.pos_config_id}`">
|
||||
<LandingPage />
|
||||
</t>
|
||||
@@ -29,13 +32,13 @@
|
||||
<t t-set-slot="stand_number" route="`/pos-self/${selfOrder.pos_config_id}/stand_number`">
|
||||
<StandNumberPage />
|
||||
</t>
|
||||
<t t-set-slot="closed" route="`/pos-self/${selfOrder.pos_config_id}/closed`">
|
||||
<ClosedPage />
|
||||
</t>
|
||||
<t t-set-slot="orderHistory" route="`/pos-self/${selfOrder.pos_config_id}/orders`">
|
||||
<OrdersHistoryPage />
|
||||
</t>
|
||||
</Router>
|
||||
<div t-else="" class="h-100 w-100 d-flex align-items-center justify-content-center text-center">
|
||||
Hey, looks like you forgot to create products or add them to pos_config. Please add them before using the Self Order
|
||||
</div>
|
||||
<MainComponentsContainer />
|
||||
</t>
|
||||
</templates>
|
||||
|
||||
@@ -106,6 +106,12 @@ export class SelfOrder extends Reactive {
|
||||
return product;
|
||||
});
|
||||
|
||||
this.combos = this.combos.map((c) => {
|
||||
const combo = new Combo(c);
|
||||
this.comboByIds[combo.id] = combo;
|
||||
return combo;
|
||||
});
|
||||
|
||||
this.productsGroupedByCategory = this.products.reduce((acc, product) => {
|
||||
product.pos_categ_ids.map((pos_categ_ids) => {
|
||||
acc[pos_categ_ids] = acc[pos_categ_ids] || [];
|
||||
@@ -121,11 +127,14 @@ export class SelfOrder extends Reactive {
|
||||
.sort((a, b) => categorySorter(a, b, this.config.iface_start_categ_id))
|
||||
);
|
||||
|
||||
this.combos = this.combos.map((c) => {
|
||||
const combo = new Combo(c);
|
||||
this.comboByIds[combo.id] = combo;
|
||||
return combo;
|
||||
});
|
||||
if (this.categoryList.size === 0) {
|
||||
this.categoryList.add({
|
||||
has_image: false,
|
||||
id: 0,
|
||||
name: _t("Other"),
|
||||
sequence: -1,
|
||||
});
|
||||
}
|
||||
|
||||
this.currentCategory = this.pos_category.length > 0 ? [...this.categoryList][0] : null;
|
||||
}
|
||||
@@ -197,6 +206,10 @@ export class SelfOrder extends Reactive {
|
||||
}
|
||||
|
||||
async sendDraftOrderToServer() {
|
||||
if (this.currentOrder.isSavedOnServer || this.currentOrder.lines.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
const rpcUrl = this.currentOrder.isAlreadySent
|
||||
? "/pos-self-order/update-existing-order"
|
||||
@@ -308,18 +321,6 @@ export class SelfOrder extends Reactive {
|
||||
this.currentOrder.updateDataFromServer(order);
|
||||
}
|
||||
|
||||
isSession() {
|
||||
if (this.config.self_ordering_mode !== "kiosk") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.pos_session || !this.pos_session.id) {
|
||||
this.router.navigate("closed");
|
||||
} else if (this.router.activeSlot === "closed") {
|
||||
this.router.navigate("default");
|
||||
}
|
||||
}
|
||||
|
||||
isOrder() {
|
||||
if (!this.currentOrder || !this.currentOrder.lines.length) {
|
||||
this.router.navigate("default");
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
<?xml version="1.0"?>
|
||||
<odoo>
|
||||
<record id="custom_link_action" model="ir.actions.act_window">
|
||||
<field name="name">Custom Links</field>
|
||||
<field name="res_model">pos_self_order.custom_link</field>
|
||||
<field name="view_mode">tree</field>
|
||||
</record>
|
||||
<record model="ir.ui.view" id="custom_link_tree">
|
||||
<field name="name">custom.link.tree</field>
|
||||
<field name="model">pos_self_order.custom_link</field>
|
||||
|
||||
@@ -25,10 +25,10 @@
|
||||
<t t-set="qr_code_size" t-value="190"/>
|
||||
<t t-call="web.basic_layout">
|
||||
<div class="w-100" style="text-align: right">
|
||||
<span class="fs-4">Point of sale: <t t-esc="pos_name" /></span><span class="fs-4" style="margin-left:20px">Self Order: <t t-if="table_mode == 'mobile'">Yes</t><t t-else="">No</t></span>
|
||||
<span class="fs-4">Point of sale: <t t-esc="pos_name" /></span><span class="fs-4" style="margin-left:20px">Self Order: <t t-if="self_order">Yes</t><t t-else="">No</t></span>
|
||||
</div>
|
||||
<div class="mb-5" style="border-bottom: 1px solid black;">
|
||||
<h2 t-if="table_mode == 'mobile'">Make it easy for your customers to explore your menu
|
||||
<h2 t-if="table_mode">Make it easy for your customers to explore your menu
|
||||
online or order with the QR codes on your tables</h2>
|
||||
<h2 t-else="">Make it easy for your customers to explore your menu
|
||||
online with the QR codes on your tables</h2>
|
||||
@@ -36,7 +36,7 @@
|
||||
|
||||
<div>
|
||||
<h3>How to use</h3>
|
||||
<t t-if="table_mode == 'mobile'">
|
||||
<t t-if="table_mode">
|
||||
<p>Each table in your floor plan is assigned a unique QR code based on your configuration. For security reasons,
|
||||
both the point of sale and table names are encrypted in the generated URL, as shown in the example below:.</p>
|
||||
<p class="mt-2">Table: <span t-if="table_example" t-esc="table_example['name']" /><br/>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
<field name="pos_self_ordering_mode" />
|
||||
<div class="d-flex flex-column align-items-start w-50" invisible="pos_self_ordering_mode == 'nothing'">
|
||||
<button class="btn-link p-0" icon="oi-arrow-right" name="preview_self_order_app" type="object" string="Preview Web interface"/>
|
||||
<button class="btn-link p-0" icon="oi-arrow-right" name="pos_self_order.custom_link_action" type="action" string="Home buttons"/>
|
||||
<button class="btn-link p-0" icon="oi-arrow-right" name="custom_link_action" type="object" string="Home buttons"/>
|
||||
<button class="btn-link p-0" icon="oi-arrow-right" name="generate_qr_codes_page" type="object" string="Print QR Codes" invisible="not pos_self_ordering_mode in ['consultation', 'mobile']"/>
|
||||
<button groups="base.group_no_one" class="btn-link p-0" icon="oi-arrow-right" name="update_access_tokens" type="object" string="Reset QR Codes" invisible="not pos_self_ordering_mode in ['consultation', 'mobile']"/>
|
||||
</div>
|
||||
@@ -46,7 +46,7 @@
|
||||
<setting string="Options" help="All options for your Self devices" invisible="pos_self_ordering_mode in ['nothing', 'consultation']">
|
||||
<div class="content-group row" invisible="not pos_self_ordering_mode in ['kiosk', 'mobile']">
|
||||
<label for="pos_self_ordering_service_mode" class="col-lg-4" string="Service at" />
|
||||
<field name="pos_self_ordering_service_mode" readonly="pos_self_ordering_pay_after == 'meal' and pos_self_ordering_mode == 'mobile'" />
|
||||
<field name="pos_self_ordering_service_mode" readonly="not pos_module_pos_restaurant and pos_self_ordering_mode != 'kiosk'" />
|
||||
</div>
|
||||
<div class="content-group row" invisible="not pos_self_ordering_mode in ['kiosk', 'mobile']">
|
||||
<label for="pos_self_ordering_default_user_id" class="col-lg-4" string="Default User"/>
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
<div id="self-payment-after" class="content-group row" invisible="not pos_self_ordering_mode in ['kiosk', 'mobile']">
|
||||
<label string="Pay after" for="pos_self_ordering_pay_after" class="col-lg-4"/>
|
||||
<field name="pos_self_ordering_pay_after" readonly="pos_self_ordering_mode == 'kiosk'" widget="upgrade_selection"/>
|
||||
<field name="pos_self_ordering_pay_after" readonly="pos_self_ordering_mode == 'kiosk' or pos_self_ordering_service_mode == 'counter' and pos_self_ordering_mode == 'mobile'" widget="upgrade_selection"/>
|
||||
</div>
|
||||
</setting>
|
||||
<setting string="Eat in / Take out" help="Adjust the tax rate based on whether customers are dining in or opting for takeout." invisible="not pos_self_ordering_mode in ['mobile', 'kiosk']">
|
||||
@@ -69,6 +69,11 @@
|
||||
</setting>
|
||||
</block>
|
||||
</block>
|
||||
|
||||
<block id="restaurant_section" position="attributes">
|
||||
<attribute name="invisible">is_kiosk_mode</attribute>
|
||||
</block>
|
||||
|
||||
<setting id="customer_display" position="attributes">
|
||||
<attribute name="invisible">is_kiosk_mode</attribute>
|
||||
</setting>
|
||||
|
||||
Reference in New Issue
Block a user