[REF] point_of_sale: unify numpads

At the moment, the point_of_sale module has 3 different implementations of
numpads. This is absurd. In this PR we unify them all into a single
numpad component.

One of the reasons why there are multiple numpads is because each requires
a slightly different set of buttons. The new `Numpad` component provides
a simple API which allows the consumer to specify what the buttons should be.

This is done by proving the `buttons` prop, which has the following type:
```js
    buttons: {
        type: Array,
        element: {
            type: Object,
            shape: {
                value: String,
                text: { type: String, optional: true },
                class: { type: String, optional: true },
                disabled: { type: Boolean, optional: true },
            },
        },
    }
```

In this PR we also provide a simple set of helper functions for the tours
and adapt all of the existing tests accordingly.

closes odoo/odoo#132245

Task: 3470346
Related: odoo/enterprise#46427
Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
This commit is contained in:
vlst
2023-09-07 14:45:20 +00:00
parent 62a8e81f28
commit b71e05e804
44 changed files with 956 additions and 1197 deletions
@@ -0,0 +1,35 @@
/** @odoo-module */
import { useService } from "@web/core/utils/hooks";
import { Component } from "@odoo/owl";
export class Numpad extends Component {
static template = "point_of_sale.Numpad";
static props = {
class: { type: String, optional: true },
onClick: { type: Function, optional: true },
buttons: {
type: Array,
element: {
type: Object,
shape: {
value: String,
text: { type: String, optional: true },
class: { type: String, optional: true },
disabled: { type: Boolean, optional: true },
},
},
},
};
static defaultProps = {
class: "",
};
setup() {
if (!this.props.onClick) {
this.numberBuffer = useService("number_buffer");
this.onClick = (buttonValue) => this.numberBuffer.sendKey(buttonValue);
} else {
this.onClick = this.props.onClick;
}
}
}
@@ -0,0 +1,3 @@
.max-width-325px {
max-width: 325px;
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.Numpad">
<div t-attf-class="{{props.class}} numpad row row-cols-{{props.buttons.length / 4}} gx-0">
<button t-foreach="props.buttons" t-as="button" t-key="button.value"
t-attf-class="col btn btn-light py-3 border fw-bolder rounded-0 {{ button.class or '' }}"
t-on-click="() => this.onClick(button.value)"
t-att-disabled="button.disabled"
t-esc="button.text or button.value" />
</div>
</t>
</templates>
@@ -1,14 +0,0 @@
/** @odoo-module */
import { PSNumpadInputButton } from "@point_of_sale/app/screens/payment_screen/numpad/numpad_button/numpad_button";
import { Component } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
export class PaymentScreenNumpad extends Component {
static components = { PSNumpadInputButton };
static template = "point_of_sale.PaymentScreenNumpad";
setup() {
this.decimalPoint = useService("localization").decimalPoint;
}
}
@@ -1,15 +0,0 @@
.payment-numpad .numpad button {
font-size: clamp(map-get($font-sizes, 6), 3vw, 36px);
}
.payment-numpad .numpad button:nth-child(16) img {
width: 35%;
max-width: 64px;
height: auto;
}
@include media-breakpoint-down(md) {
.payment-numpad .numpad button:nth-child(16) img {
max-width: 48px;
}
}
@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.PaymentScreenNumpad">
<div class="numpad d-grid text-center flex-grow-1 h-100 w-100">
<PSNumpadInputButton value="'1'" />
<PSNumpadInputButton value="'2'" />
<PSNumpadInputButton value="'3'" />
<PSNumpadInputButton value="'+10'" changeClassTo="'mode-button'" />
<PSNumpadInputButton value="'4'" />
<PSNumpadInputButton value="'5'" />
<PSNumpadInputButton value="'6'" />
<PSNumpadInputButton value="'+20'" changeClassTo="'mode-button'" />
<PSNumpadInputButton value="'7'" />
<PSNumpadInputButton value="'8'" />
<PSNumpadInputButton value="'9'" />
<PSNumpadInputButton value="'+50'" changeClassTo="'mode-button'" />
<PSNumpadInputButton value="'-'" text="'+/-'" />
<PSNumpadInputButton value="'0'" />
<PSNumpadInputButton value="decimalPoint" />
<PSNumpadInputButton value="'Backspace'">
<img src="/point_of_sale/static/src/img/backspace.png" width="24" height="21"
alt="Backspace" />
</PSNumpadInputButton>
</div>
</t>
</templates>
@@ -1,16 +0,0 @@
/** @odoo-module */
import { Component } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
export class PSNumpadInputButton extends Component {
static template = "point_of_sale.PSNumpadInputButton";
setup() {
this.numberBuffer = useService("number_buffer");
}
get _class() {
return this.props.changeClassTo || "input-button number-char";
}
}
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.PSNumpadInputButton">
<button t-attf-class="{{ _class }} btn btn-light w-100 rounded-0 py-3"
t-on-click="() => this.numberBuffer.sendKey(props.value)">
<t t-slot="default">
<t t-if="props.text">
<h1 t-esc="props.text" />
</t>
<t t-else="">
<h1 t-esc="props.value" />
</t>
</t>
</button>
</t>
</templates>
@@ -13,17 +13,17 @@ import { DatePickerPopup } from "@point_of_sale/app/utils/date_picker_popup/date
import { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_popup";
import { ConnectionLostError } from "@web/core/network/rpc_service";
import { PaymentScreenNumpad } from "@point_of_sale/app/screens/payment_screen/numpad/numpad";
import { PaymentScreenPaymentLines } from "@point_of_sale/app/screens/payment_screen/payment_lines/payment_lines";
import { PaymentScreenStatus } from "@point_of_sale/app/screens/payment_screen/payment_status/payment_status";
import { usePos } from "@point_of_sale/app/store/pos_hook";
import { Component, useState, useRef } from "@odoo/owl";
import { renderToElement } from "@web/core/utils/render";
import { Numpad } from "@point_of_sale/app/generic_components/numpad/numpad";
export class PaymentScreen extends Component {
static template = "point_of_sale.PaymentScreen";
static components = {
PaymentScreenNumpad,
Numpad,
PaymentScreenPaymentLines,
PaymentScreenStatus,
};
@@ -47,6 +47,26 @@ export class PaymentScreen extends Component {
this.error = false;
this.validateOrder = useAsyncLockedMethod(this.validateOrder);
}
getNumpadButtons() {
return [
{ value: "1" },
{ value: "2" },
{ value: "3" },
{ value: "+10" },
{ value: "4" },
{ value: "5" },
{ value: "6" },
{ value: "+20" },
{ value: "7" },
{ value: "8" },
{ value: "9" },
{ value: "+50" },
{ value: "-", text: "+/-" },
{ value: "0" },
{ value: this.env.services.localization.decimalPoint },
{ value: "Backspace", text: "⌫" },
];
}
showMaxValueError() {
this.popup.add(ErrorPopup, {
@@ -20,9 +20,7 @@
</div>
<div class="center-content d-flex flex-column w-50 p-1 border-start border-end bg-300" >
<PaymentScreenStatus order="currentOrder" />
<div class="payment-numpad flex-grow-1 d-flex flex-wrap">
<PaymentScreenNumpad />
</div>
<Numpad class="'flex-grow-1'" buttons="getNumpadButtons()" />
</div>
<div class="right-content w-25 bg-400">
<t t-call="point_of_sale.PaymentScreenButtons" />
@@ -55,7 +53,8 @@
</div>
</t>
<t t-else="">
<div class="button next validation btn btn-primary btn-lg py-5 rounded-0 d-flex flex-column align-items-center justify-content-center fw-bolder" t-attf-class="{{currentOrder.is_paid() and currentOrder._isValidEmptyOrder() ? 'highlight' : 'disabled'}}"
<div class="button next validation btn btn-primary btn-lg py-5 rounded-0 d-flex flex-column align-items-center justify-content-center fw-bolder"
t-attf-class="{{currentOrder.is_paid() and currentOrder._isValidEmptyOrder() ? 'highlight' : 'disabled'}}"
t-on-click="() => this.validateOrder()">
<div class="pay-circle d-flex align-items-center justify-content-center mb-2">
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
@@ -65,7 +64,6 @@
</t>
</t>
<t t-name="point_of_sale.PaymentScreenButtons">
<div class="payment-buttons d-flex flex-column flex-wrap">
<button class="button partner-button btn btn-light py-3 text-start rounded-0 border-bottom"
@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.CategoryButton">
<button class="category-button btn btn-light" t-on-click="() => this.props.switchCategory(props.category.id)">
<div class="category-img">
<img t-att-src="imageUrl" alt="Category" />
</div>
<div class="category-name mt-2 fw-bolder">
<t t-esc="props.category.name" />
</div>
</button>
</t>
</templates>
@@ -1,48 +0,0 @@
/** @odoo-module */
import { useService } from "@web/core/utils/hooks";
import { Component } from "@odoo/owl";
import { usePos } from "@point_of_sale/app/store/pos_hook";
/**
* @prop {'quantity' | 'price' | 'discount'} activeMode
* @prop {Array<'quantity' | 'price' | 'discount'>} disabledModes
* @prop {boolean} disableSign
*/
export class NumpadWidget extends Component {
static template = "point_of_sale.NumpadWidget";
static defaultProps = {
disabledModes: [],
disableSign: false,
};
setup() {
this.pos = usePos();
this.numberBuffer = useService("number_buffer");
this.localization = useService("localization");
}
get hasPriceControlRights() {
return (
this.pos.cashierHasPriceControlRights() && !this.props.disabledModes.includes("price")
);
}
get hasManualDiscount() {
return this.pos.config.manual_discount && !this.props.disabledModes.includes("discount");
}
changeMode(mode) {
if (!this.hasPriceControlRights && mode === "price") {
return;
}
if (!this.hasManualDiscount && mode === "discount") {
return;
}
this.numberBuffer.capture();
this.numberBuffer.reset();
this.pos.numpadMode = mode;
}
sendInput(key) {
this.numberBuffer.sendKey(key);
}
get decimalSeparator() {
return this.localization.decimalPoint;
}
}
@@ -1,10 +0,0 @@
.numpad {
grid-template-columns: repeat(4, 1fr);
gap: 1px;
}
.numpad .disabled-mode, .pos .numpad .disabled-mode:hover {
background: $gray-200;
color: $gray-500;
cursor: not-allowed;
}
@@ -1,40 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.NumpadWidget">
<div class="numpad d-grid text-center flex-grow-1 bg-300">
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('1')">1</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('2')">2</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('3')">3</button>
<button class="mode-button btn btn-light w-100 rounded-0 py-3 fw-bolder" t-att-class="{'selected-mode active': props.activeMode === 'quantity'}"
t-on-click="() => this.changeMode('quantity')">Qty</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('4')">4</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('5')">5</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('6')">6</button>
<button class="mode-button btn btn-light w-100 rounded-0 py-3 fw-bolder text-nowrap" t-att-class="{
'selected-mode active': props.activeMode === 'discount',
'disabled-mode': !hasManualDiscount
}"
t-att-disabled="!hasManualDiscount"
t-on-click="() => this.changeMode('discount')">% Disc</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('7')">7</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('8')">8</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('9')">9</button>
<button class="mode-button btn btn-light w-100 rounded-0 py-3 fw-bolder" t-att-class="{
'selected-mode active': props.activeMode === 'price',
'disabled-mode': !hasPriceControlRights
}" t-att-disabled="!hasPriceControlRights"
t-on-click="() => this.changeMode('price')">Price</button>
<button class="input-button px-4 numpad-minus btn btn-light w-100 rounded-0 py-3 fw-bolder" t-att-class="{ 'disabled-mode': props.disableSign }" t-on-click="() => this.sendInput('-')">+/-</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('0')">0</button>
<button class="input-button px-4 number-char btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput(decimalSeparator)">
<t t-esc="decimalSeparator" />
</button>
<button class="input-button px-4 numpad-backspace btn btn-light w-100 rounded-0 py-3 fw-bolder" t-on-click="() => this.sendInput('Backspace')">
<img style="pointer-events: none;" src="/point_of_sale/static/src/img/backspace.png"
width="24" height="21" alt="Backspace" />
</button>
</div>
</t>
</templates>
@@ -16,7 +16,7 @@ import { usePos } from "@point_of_sale/app/store/pos_hook";
import { Component, onMounted, useState } from "@odoo/owl";
import { ErrorBarcodePopup } from "@point_of_sale/app/barcode/error_popup/barcode_error_popup";
import { NumpadWidget } from "@point_of_sale/app/screens/product_screen/numpad/numpad";
import { Numpad } from "@point_of_sale/app/generic_components/numpad/numpad";
import { OrderWidget } from "@point_of_sale/app/screens/product_screen/order/order";
import { ProductsWidget } from "@point_of_sale/app/screens/product_screen/product_list/product_list";
import { ActionpadWidget } from "@point_of_sale/app/screens/product_screen/action_pad/action_pad";
@@ -25,7 +25,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
static template = "point_of_sale.ProductScreen";
static components = {
ActionpadWidget,
NumpadWidget,
Numpad,
OrderWidget,
ProductsWidget,
};
@@ -63,6 +63,40 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
onMounted() {
this.pos.openCashControl();
}
getNumpadButtons() {
return [
{ value: "1" },
{ value: "2" },
{ value: "3" },
{ value: "quantity", text: "Qty" },
{ value: "4" },
{ value: "5" },
{ value: "6" },
{ value: "discount", text: "% Disc", disabled: !this.pos.config.manual_discount },
{ value: "7" },
{ value: "8" },
{ value: "9" },
{ value: "price", text: "Price", disabled: !this.pos.cashierHasPriceControlRights() },
{ value: "-", text: "+/-" },
{ value: "0" },
{ value: this.env.services.localization.decimalPoint },
// Unicode: https://www.compart.com/en/unicode/U+232B
{ value: "Backspace", text: "⌫" },
].map((button) => ({
...button,
class: this.pos.numpadMode === button.value ? "active border-primary" : "",
}));
}
onNumpadClick(buttonValue) {
if (["quantity", "discount", "price"].includes(buttonValue)) {
this.numberBuffer.capture();
this.numberBuffer.reset();
this.pos.numpadMode = buttonValue;
return;
}
this.numberBuffer.sendKey(buttonValue);
}
/**
* To be overridden by modules that checks availability of
* connected scale.
@@ -20,9 +20,7 @@
actionName="constructor.numpadActionName"
actionType="'payment'"
onClickMore.bind="displayAllControlPopup" />
<NumpadWidget
updateSelectedOrderline.bind="updateSelectedOrderline"
activeMode="pos.numpadMode" />
<Numpad buttons="getNumpadButtons()" onClick.bind="onNumpadClick" class="'w-100'"/>
</div>
</div>
</div>
@@ -12,12 +12,12 @@ import { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_pop
import { ActionpadWidget } from "@point_of_sale/app/screens/product_screen/action_pad/action_pad";
import { InvoiceButton } from "@point_of_sale/app/screens/ticket_screen/invoice_button/invoice_button";
import { NumpadWidget } from "@point_of_sale/app/screens/product_screen/numpad/numpad";
import { OrderDetails } from "@point_of_sale/app/screens/ticket_screen/order_details/order_details";
import { ReprintReceiptButton } from "@point_of_sale/app/screens/ticket_screen/reprint_receipt_button/reprint_receipt_button";
import { SearchBar } from "@point_of_sale/app/screens/ticket_screen/search_bar/search_bar";
import { usePos } from "@point_of_sale/app/store/pos_hook";
import { Component, onMounted, useState } from "@odoo/owl";
import { Numpad } from "@point_of_sale/app/generic_components/numpad/numpad";
const { DateTime } = luxon;
@@ -27,10 +27,10 @@ export class TicketScreen extends Component {
static components = {
ActionpadWidget,
InvoiceButton,
NumpadWidget,
OrderDetails,
ReprintReceiptButton,
SearchBar,
Numpad,
};
static defaultProps = {
destinationOrder: null,
@@ -85,6 +85,26 @@ export class TicketScreen extends Component {
await this._fetchSyncedOrders();
}
}
getNumpadButtons() {
return [
{ value: "1" },
{ value: "2" },
{ value: "3" },
{ value: "quantity", text: "Qty", class: "active border-primary" },
{ value: "4" },
{ value: "5" },
{ value: "6" },
{ value: "discount", text: "% Disc", disabled: true },
{ value: "7" },
{ value: "8" },
{ value: "9" },
{ value: "price", text: "Price", disabled: true },
{ value: "-", text: "+/-", disabled: true },
{ value: "0" },
{ value: this.env.services.localization.decimalPoint },
{ value: "Backspace", text: "⌫" },
];
}
async onSearch(search) {
Object.assign(this._state.ui.searchDetails, search);
if (this._state.ui.filter == "SYNCED") {
@@ -135,11 +135,7 @@
actionType="'refund'"
actionToTrigger.bind="onDoRefund"
isActionButtonHighlighted="getHasItemsToRefund()" />
<NumpadWidget
disabledModes="['price', 'discount']"
setNumpadMode="() => {}"
activeMode="_selectedOrderlineId and 'quantity'"
disableSign="true" />
<Numpad buttons="getNumpadButtons()" class="'max-width-325px'"/>
</div>
</div>
</t>
@@ -4,9 +4,11 @@ import { _t } from "@web/core/l10n/translation";
import { AbstractAwaitablePopup } from "@point_of_sale/app/popup/abstract_awaitable_popup";
import { useService } from "@web/core/utils/hooks";
import { useState, useRef, onMounted } from "@odoo/owl";
import { Numpad } from "@point_of_sale/app/generic_components/numpad/numpad";
export class NumberPopup extends AbstractAwaitablePopup {
static template = "point_of_sale.NumberPopup";
static components = { Numpad };
static defaultProps = {
confirmText: _t("Confirm"),
cancelText: _t("Discard"),
@@ -33,7 +35,6 @@ export class NumberPopup extends AbstractAwaitablePopup {
*/
setup() {
super.setup();
this.localization = useService("localization");
let startingBuffer = "";
let startingPayload = null;
if (typeof this.props.startingValue === "number" && this.props.startingValue > 0) {
@@ -62,8 +63,26 @@ export class NumberPopup extends AbstractAwaitablePopup {
this.inputRef.el.focus();
}
}
get decimalSeparator() {
return this.localization.decimalPoint;
getNumpadButtons() {
const { isPassword, cheap } = this.props;
return [
{ value: "1" },
{ value: "2" },
{ value: "3" },
...(!isPassword ? [{ value: cheap ? "+1" : "+10" }] : []),
{ value: "4" },
{ value: "5" },
{ value: "6" },
...(!isPassword ? [{ value: cheap ? "+2" : "+20" }] : []),
{ value: "7" },
{ value: "8" },
{ value: "9" },
...(!isPassword ? [{ value: "-" }] : []),
{ value: "Delete", text: "C" },
{ value: "0" },
...(!isPassword ? [{ value: this.env.services.localization.decimalPoint }] : []),
{ value: "Backspace", text: "⌫" },
];
}
get inputBuffer() {
if (this.state.buffer === null) {
@@ -80,9 +99,6 @@ export class NumberPopup extends AbstractAwaitablePopup {
super.confirm();
}
}
sendInput(key) {
this.numberBuffer.sendKey(key);
}
getPayload() {
let startingPayload = null;
if (typeof this.props.startingValue === "number" && this.props.startingValue > 0) {
@@ -1,5 +0,0 @@
.popup-numpad .input-button,
.popup-numpad .mode-button {
height: 50px;
width: 50px;
}
@@ -13,48 +13,7 @@
<span t-if="props.inputSuffix"><t t-esc="props.inputSuffix" /></span>
</div>
</div>
<div class="popup-numpad px-5 my-3">
<!-- FIXME POSREF do we really need to hardcode all of these? -->
<div class="row">
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('1')">1</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('2')">2</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('3')">3</button>
<t t-if="!props.isPassword and props.cheap">
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('+1')">+1</button>
</t>
<t t-if="!props.isPassword and !props.cheap">
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('+10')">+10</button>
</t>
</div>
<div class="row">
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('4')">4</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('5')">5</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('6')">6</button>
<t t-if="!props.isPassword and props.cheap">
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('+2')">+2</button>
</t>
<t t-if="!props.isPassword and !props.cheap">
<button class="mode-button add btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('+20')">+20</button>
</t>
</div>
<div class="row">
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('7')">7</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('8')">8</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('9')">9</button>
<button t-if="!props.isPassword" class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('-')">-</button>
</div>
<div class="row">
<button class="col-3 input-button numpad-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('Delete')">C</button>
<button class="col-3 input-button number-char btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('0')">0</button>
<button t-if="!props.isPassword" class="col-3 input-button number-char dot btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput(decimalSeparator)">
<t t-esc="decimalSeparator" /></button>
<button class="col-3 input-button numpad-backspace btn btn-secondary p-0 rounded-circle m-1 fw-bolder" t-on-mousedown.prevent="() => this.sendInput('Backspace')">
<img style="pointer-events: none;"
src="/point_of_sale/static/src/img/backspace.png" width="24"
height="21" alt="Backspace" />
</button>
</div>
</div>
<Numpad buttons="getNumpadButtons()" class="'mx-auto my-3 w-75 max-width-325px'"/>
<footer class="footer centered modal-footer justify-content-center">
<button class="button confirm highlight btn btn-lg btn-primary" t-on-mousedown.prevent="confirm">
<span><t t-esc="props.confirmText" /></span>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

@@ -19,7 +19,7 @@ registry
ProductScreen.do.clickDisplayedProduct("Zero Amount Product");
ProductScreen.check.selectedOrderlineHas("Zero Amount Product", "1.0", "1.0");
ProductScreen.do.pressNumpad("+/- 1");
ProductScreen.do.pressNumpad("+/-", "1");
ProductScreen.check.selectedOrderlineHas("Zero Amount Product", "-1.0", "-1.0");
ProductScreen.do.clickPayButton();
@@ -28,7 +28,7 @@ registry
PaymentScreen.check.changeIs("0.0");
PaymentScreen.check.validateButtonIsHighlighted(false);
// remove the selected paymentline with multiple backspace presses
PaymentScreen.do.pressNumpad("Backspace Backspace");
PaymentScreen.do.pressNumpad("⌫ ⌫");
PaymentScreen.do.fillPaymentLineAmountMobile("Cash", "0");
PaymentScreen.check.selectedPaymentlineHas("Cash", "0.00");
PaymentScreen.do.clickPaymentlineDelButton("Cash", "0", true);
@@ -66,7 +66,7 @@ registry.category("web_tour.tours").add("PosComboPriceTaxIncludedTour", {
...ErrorPopup.do.clickConfirm(),
// check that removing a combo product removes all the combo products
...ProductScreen.do.pressNumpad("Backspace"),
...ProductScreen.do.pressNumpad("⌫"),
...ProductScreen.check.orderIsEmpty(),
...ProductScreen.do.clickDisplayedProduct("Office Combo"),
@@ -34,11 +34,11 @@ registry.category("web_tour.tours").add("ProductScreenTour", {
// Check effects of clicking numpad buttons
ProductScreen.do.clickOrderline("Letter Tray", "1");
ProductScreen.check.selectedOrderlineHas("Letter Tray", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Letter Tray", "0.0", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "3", "15.30");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "0.0", "0.0");
ProductScreen.do.pressNumpad("1");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "1.0", "5.1");
@@ -46,21 +46,21 @@ registry.category("web_tour.tours").add("ProductScreenTour", {
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "12.0", "61.2");
ProductScreen.do.pressNumpad("3");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "123.0", "627.3");
ProductScreen.do.pressNumpad(". 5");
ProductScreen.do.pressNumpad(".", "5");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "123.5", "629.85");
ProductScreen.do.pressNumpad("Price");
ProductScreen.check.modeIsActive("Price");
ProductScreen.do.pressNumpad("1");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "123.5", "123.5");
ProductScreen.do.pressNumpad("1 .");
ProductScreen.do.pressNumpad("1", ".");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "123.5", "1,358.5");
ProductScreen.do.pressNumpad("Disc");
ProductScreen.check.modeIsActive("Disc");
ProductScreen.do.pressNumpad("5 .");
ProductScreen.do.pressNumpad("% Disc");
ProductScreen.check.modeIsActive("% Disc");
ProductScreen.do.pressNumpad("5", ".");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "123.5", "1,290.58");
ProductScreen.do.pressNumpad("Qty");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.orderIsEmpty();
// Check different subcategories
@@ -85,13 +85,13 @@ registry.category("web_tour.tours").add("ProductScreenTour", {
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "1.0");
ProductScreen.do.pressNumpad("2");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "2.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.orderIsEmpty();
// Add multiple orderlines then delete each of them until empty
@@ -102,31 +102,31 @@ registry.category("web_tour.tours").add("ProductScreenTour", {
ProductScreen.do.clickDisplayedProduct("Monitor Stand");
ProductScreen.do.clickOrderline("Whiteboard Pen", "1.0");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.0");
ProductScreen.do.clickOrderline("Wall Shelf Unit", "1.0");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.0");
ProductScreen.do.clickOrderline("Small Shelf", "1.0");
ProductScreen.check.selectedOrderlineHas("Small Shelf", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Small Shelf", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.0");
ProductScreen.do.clickOrderline("Magnetic Board", "1.0");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "0.0");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.orderIsEmpty();
// Test OrderlineCustomerNoteButton
@@ -116,7 +116,6 @@ registry.category("web_tour.tours").add("TicketScreenTour", {
TicketScreen.do.clickBackToMainTicketScreen();
// When going back, the ticket screen should be in its previous state.
TicketScreen.check.filterIs("Paid");
// Test refund //
TicketScreen.do.clickDiscard();
ProductScreen.check.isShown();
@@ -127,7 +126,7 @@ registry.category("web_tour.tours").add("TicketScreenTour", {
TicketScreen.do.selectOrder("-0005");
TicketScreen.check.partnerIs("Colleen Diaz");
TicketScreen.do.clickOrderline("Desk Pad");
TicketScreen.do.pressNumpad("3");
ProductScreen.do.pressNumpad("3");
// Error should show because 2 is more than the number
// that can be refunded.
ErrorPopup.do.clickConfirm();
@@ -138,7 +137,7 @@ registry.category("web_tour.tours").add("TicketScreenTour", {
ProductScreen.do.clickRefund();
TicketScreen.do.selectOrder("-0005");
TicketScreen.do.clickOrderline("Desk Pad");
TicketScreen.do.pressNumpad("1");
ProductScreen.do.pressNumpad("1");
TicketScreen.check.toRefundTextContains("To Refund: 1.00");
TicketScreen.do.confirmRefund();
ProductScreen.do.goBackToMainScreen();
@@ -150,10 +149,10 @@ registry.category("web_tour.tours").add("TicketScreenTour", {
ErrorPopup.do.clickConfirm();
// Change the refund line quantity to -3 -- not allowed
// so error popup.
ProductScreen.do.pressNumpad("+/- 3");
ProductScreen.do.pressNumpad("+/-", "3");
ErrorPopup.do.clickConfirm();
// Change the refund line quantity to -2 -- allowed.
ProductScreen.do.pressNumpad("+/- 2");
ProductScreen.do.pressNumpad("+/-", "2");
ProductScreen.check.selectedOrderlineHas("Desk Pad", "-2.00");
// Check if the amount being refunded changed to 2.
ProductScreen.do.clickRefund();
@@ -1,6 +1,7 @@
/** @odoo-module */
import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods";
import { Numpad } from "@point_of_sale/../tests/tours/helpers/NumpadTourMethods";
import { registry } from "@web/core/registry";
function add_product_to_order(product_name) {
@@ -66,13 +67,7 @@ function set_fiscal_position_on_order(fp_name) {
}
function press_payment_numpad(val) {
return [
{
content: `press ${val} on payment screen numpad`,
trigger: `.payment-numpad .input-button:contains("${val}"):visible`,
mobile: false,
},
];
return [{ ...Numpad.click(val), mobile: false }];
}
function fillPaymentLineAmountMobile(lineName, keys) {
@@ -107,10 +102,7 @@ function press_product_numpad(val) {
trigger: ".btn-switchpane:contains('Review')",
mobile: true,
},
{
content: `press ${val} on product screen numpad`,
trigger: `.numpad .input-button:contains("${val}"):visible`,
},
Numpad.click(val),
{
content: "go back to the products",
trigger: ".floor-button",
@@ -1,6 +1,7 @@
/** @odoo-module */
import { createTourMethods } from "@point_of_sale/../tests/tours/helpers/utils";
import { Numpad } from "@point_of_sale/../tests/tours/helpers/NumpadTourMethods";
class Do {
/**
@@ -10,34 +11,11 @@ class Do {
* @param {String} keys space-separated input keys
*/
pressNumpad(keys) {
const numberChars = "0 1 2 3 4 5 6 7 8 9 C".split(" ");
const modeButtons = "+1 +10 +2 +20 +5 +50".split(" ");
const decimalSeparators = ", .".split(" ");
function generateStep(key) {
let trigger;
if (numberChars.includes(key)) {
trigger = `.popup-numpad .number-char:contains("${key}")`;
} else if (modeButtons.includes(key)) {
trigger = `.popup-numpad .mode-button:contains("${key}")`;
} else if (key === "Backspace") {
trigger = `.popup-numpad .numpad-backspace`;
} else if (decimalSeparators.includes(key)) {
trigger = `.popup-numpad .number-char.dot`;
}
return {
content: `'${key}' pressed in numpad`,
trigger,
mobile: false,
};
}
return keys.split(" ").map(generateStep);
return keys.split(" ").map((key) => Numpad.click(key, { mobile: false }));
}
enterValue(keys) {
const numpadKeys = keys.split('').join(' ');
return [
...this.pressNumpad(numpadKeys),
...this.fillPopupValue(keys)
];
const numpadKeys = keys.split("").join(" ");
return [...this.pressNumpad(numpadKeys), ...this.fillPopupValue(keys)];
}
fillPopupValue(keys) {
return [
@@ -60,7 +38,7 @@ class Do {
content: "click confirm button",
trigger: ".popup .footer .confirm",
mobile: true,
}
},
];
}
}
@@ -0,0 +1,20 @@
/** @odoo-module */
const buttonTriger = (buttonValue) => `div.numpad.row button.col:contains("${buttonValue}")`;
export const Numpad = {
click: (buttonValue, options = {}) => ({
content: `click numpad button: ${buttonValue}`,
trigger: buttonTriger(buttonValue),
run: () => {
[...$(buttonTriger(buttonValue))]
.filter((el) => el.innerHTML == buttonValue)[0]
?.click();
},
mobile: options.mobile,
}),
isActive: (buttonValue) => ({
content: `check if --${buttonValue}-- mode is activated`,
trigger: `${buttonTriger(buttonValue)}.active`,
isCheck: true,
}),
};
@@ -1,6 +1,7 @@
/** @odoo-module */
import { createTourMethods } from "@point_of_sale/../tests/tours/helpers/utils";
import { Numpad } from "@point_of_sale/../tests/tours/helpers/NumpadTourMethods";
class Do {
clickPaymentMethod(name) {
@@ -86,24 +87,7 @@ class Do {
* @param {String} keys space-separated numpad keys
*/
pressNumpad(keys) {
const numberChars = ". +/- 0 1 2 3 4 5 6 7 8 9".split(" ");
const modeButtons = "+10 +20 +50".split(" ");
function generateStep(key) {
let trigger;
if (numberChars.includes(key)) {
trigger = `.payment-numpad .number-char:contains("${key}")`;
} else if (modeButtons.includes(key)) {
trigger = `.payment-numpad .mode-button:contains("${key}")`;
} else if (key === "Backspace") {
trigger = `.payment-numpad .number-char img[alt="Backspace"]`;
}
return {
content: `'${key}' pressed in payment numpad`,
trigger,
mobile: false,
};
}
return keys.split(" ").map(generateStep);
return keys.split(" ").map((key) => Numpad.click(key, { mobile: false }));
}
clickBack() {
@@ -2,7 +2,7 @@
import { createTourMethods } from "@point_of_sale/../tests/tours/helpers/utils";
import { TextAreaPopup } from "@point_of_sale/../tests/tours/helpers/TextAreaPopupTourMethods";
import { Numpad } from "@point_of_sale/../tests/tours/helpers/NumpadTourMethods";
class Do {
clickDisplayedProduct(name) {
return [
@@ -70,34 +70,16 @@ class Do {
* NOTE: Maximum of 2 characters because NumberBuffer only allows 2 consecutive
* fast inputs. Fast inputs is the case in tours.
*
* @param {String} keys space-separated numpad keys
* @param {...String} keys space-separated numpad keys
*/
pressNumpad(keys) {
const numberChars = ". 0 1 2 3 4 5 6 7 8 9".split(" ");
const modeButtons = "Qty Price Disc".split(" ");
function generateStep(key) {
let trigger;
if (numberChars.includes(key)) {
trigger = `.numpad .number-char:contains("${key}")`;
} else if (modeButtons.includes(key)) {
trigger = `.numpad .mode-button:contains("${key}")`;
} else if (key === "Backspace") {
trigger = `.numpad .numpad-backspace`;
} else if (key === "+/-") {
trigger = `.numpad .numpad-minus`;
}
return {
content: `'${key}' pressed in product screen numpad`,
trigger,
};
}
pressNumpad(...keys) {
return [
{
content: "click review button",
trigger: ".btn-switchpane:contains('Review')",
mobile: true,
},
...keys.split(" ").map(generateStep),
...keys.map(Numpad.click),
{
content: "go back to the products",
trigger: ".pos-rightheader .floor-button",
@@ -456,11 +438,7 @@ class Check {
trigger: ".btn-switchpane:contains('Review')",
mobile: true,
},
{
content: `'${mode}' is active`,
trigger: `.numpad button.selected-mode:contains('${mode}')`,
run: function () {},
},
Numpad.isActive(mode),
{
content: "go back to the products",
trigger: ".pos-rightheader .floor-button",
@@ -576,20 +554,27 @@ class Execute {
*/
addOrderline(productName, quantity = 1, unitPrice = undefined, expectedTotal = undefined) {
const res = this._do.clickDisplayedProduct(productName);
const mapKey = (key) => {
if (key === "-") {
return "+/-";
}
return key;
};
const numpadWrite = (val) =>
val
.toString()
.split("")
.flatMap((key) => this._do.pressNumpad(mapKey(key)));
res.push(...this._check.selectedOrderlineHas(productName, "1.00"));
if (unitPrice) {
res.push(...this._do.pressNumpad("Price"));
res.push(...this._check.modeIsActive("Price"));
res.push(...this._do.pressNumpad(unitPrice.toString().split("").join(" ")));
res.push(...numpadWrite(unitPrice));
res.push(...this._do.pressNumpad("Qty"));
res.push(...this._check.modeIsActive("Qty"));
}
for (const char of quantity.toString() == "1" ? "" : quantity.toString()) {
if (".0123456789".includes(char)) {
res.push(...this._do.pressNumpad(char));
} else if ("-".includes(char)) {
res.push(...this._do.pressNumpad("+/-"));
}
if (quantity.toString() !== "1") {
res.push(...numpadWrite(quantity));
}
if (expectedTotal) {
res.push(...this._check.selectedOrderlineHas(productName, quantity, expectedTotal));
@@ -150,31 +150,6 @@ class Do {
},
];
}
pressNumpad(key) {
let trigger;
if (".0123456789".includes(key)) {
trigger = `.numpad .number-char:contains("${key}")`;
} else if (key === "Backspace") {
trigger = `.numpad .numpad-backspace`;
} else if (key === "+/-") {
trigger = `.numpad .numpad-minus`;
}
return [
{
content: "click review button",
trigger: ".btn-switchpane:contains('Review')",
mobile: true,
},
{
trigger,
},
{
content: "go back",
trigger: ".pos-rightheader .floor-button",
mobile: true,
},
];
}
confirmRefund() {
return [
{
@@ -5,6 +5,7 @@ import { registry } from "@web/core/registry";
import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScreenTourMethods";
import { roundDecimals as round_di } from "@web/core/utils/numbers";
import { nbsp } from "@web/core/utils/strings";
import { Numpad } from "./helpers/NumpadTourMethods";
function assert(condition, message) {
if (!condition) {
@@ -211,10 +212,7 @@ steps = steps.concat([
content: "select fixed pricelist",
trigger: ".selection-item:contains('min_quantity ordering')",
},
{
content: "change qty to 2 kg",
trigger: ".numpad button.input-button:visible:contains('2')",
},
Numpad.click("2"),
{
content: "qty of Wall Shelf line should be 2",
trigger:
@@ -250,19 +248,9 @@ steps = steps.concat([
".order-container .orderlines .orderline.selected .product-name:contains('Small Shelf') ~ .info-list .info em:contains('1.0')",
run: function () {},
},
{
content: "change to price mode",
trigger: ".numpad button:contains('Price')",
},
{
content: "make sure price mode is activated",
trigger: ".numpad button.selected-mode:contains('Price')",
run: function () {},
},
{
content: "manually override the unit price of these shelf to $5",
trigger: ".numpad button.input-button:visible:contains('5')",
},
Numpad.click("Price"),
Numpad.isActive("Price"),
Numpad.click("5"),
{
content: "Small Shelf line should be selected with unit price of 5",
trigger:
@@ -270,15 +258,8 @@ steps = steps.concat([
extra_trigger:
".order-container .orderlines .orderline.selected .product-name:contains('Small Shelf') ~ .price:contains('5.0')",
},
{
content: "change back to qty mode",
trigger: ".numpad button:contains('Qty')",
},
{
content: "make sure qty mode is activated",
trigger: ".numpad button.selected-mode:contains('Qty')",
run: function () {},
},
Numpad.click("Qty"),
Numpad.isActive("Qty"),
{
content: "click more button",
trigger: ".mobile-more-button",
@@ -91,7 +91,7 @@ registry
ProductScreen.do.clickRefund();
TicketScreen.do.selectOrder("-0001");
TicketScreen.do.clickOrderline("Magnetic Board");
TicketScreen.do.pressNumpad("1");
ProductScreen.do.pressNumpad("1");
TicketScreen.do.confirmRefund();
ProductScreen.check.isShown();
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "-1.00");
@@ -25,7 +25,7 @@ registry
ProductScreen.check.selectedOrderlineHas("Gift Card");
ProductScreen.do.pressNumpad("Price");
ProductScreen.check.modeIsActive("Price");
ProductScreen.do.pressNumpad("1 0");
ProductScreen.do.pressNumpad("1", "0");
PosLoyalty.check.orderTotalIs("10.00");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// One card for gift_card_1.
@@ -34,7 +34,7 @@ registry
ProductScreen.check.selectedOrderlineHas("Gift Card");
ProductScreen.do.pressNumpad("Price");
ProductScreen.check.modeIsActive("Price");
ProductScreen.do.pressNumpad("2 0");
ProductScreen.do.pressNumpad("2", "0");
PosLoyalty.check.orderTotalIs("20.00");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// Top up ewallet_1 for AAAAAAA.
@@ -46,7 +46,7 @@ registry
ProductScreen.do.clickCustomer("AAAAAAA");
ProductScreen.do.pressNumpad("Price");
ProductScreen.check.modeIsActive("Price");
ProductScreen.do.pressNumpad("3 0");
ProductScreen.do.pressNumpad("3", "0");
PosLoyalty.check.orderTotalIs("30.00");
PosLoyalty.exec.finalizeOrder("Cash", "30");
// Top up ewallet_2 for AAAAAAA.
@@ -56,7 +56,7 @@ registry
ProductScreen.do.clickCustomer("AAAAAAA");
ProductScreen.do.pressNumpad("Price");
ProductScreen.check.modeIsActive("Price");
ProductScreen.do.pressNumpad("4 0");
ProductScreen.do.pressNumpad("4", "0");
PosLoyalty.check.orderTotalIs("40.00");
PosLoyalty.exec.finalizeOrder("Cash", "40");
// Top up ewallet_1 for BBBBBBB.
@@ -5,184 +5,177 @@ import { ProductScreen } from "@point_of_sale/../tests/tours/helpers/ProductScre
import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils";
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("PosLoyaltyLoyaltyProgram1", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
registry
.category("web_tour.tours")
.add("PosLoyaltyLoyaltyProgram1", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
// Order1: Generates 2 points.
ProductScreen.exec.addOrderline("Whiteboard Pen", "2");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order2: Consumes points to get free product.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
// At this point, Test Partner AAA has 4 points.
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order3: Generate 4 points.
// - Initially gets free product, but was removed automatically by changing the
// number of items to zero.
// - It's impossible to checked here if the free product reward is really removed
// so we check in the backend the number of orders that consumed the reward.
ProductScreen.exec.addOrderline("Whiteboard Pen", "4");
PosLoyalty.check.orderTotalIs("12.80");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.pressNumpad("Backspace");
// At this point, the reward line should have been automatically removed
// because there is not enough points to purchase it. Unfortunately, we
// can't check that here.
PosLoyalty.check.orderTotalIs("0.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "4.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.check.orderTotalIs("12.80");
PosLoyalty.exec.finalizeOrder("Cash", "20");
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
return getSteps();
}
});
// Order1: Generates 2 points.
ProductScreen.exec.addOrderline("Whiteboard Pen", "2");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
registry
.category("web_tour.tours")
.add("PosLoyaltyLoyaltyProgram2", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.clickHomeCategory();
// Order1: Immediately set the customer to Test Partner AAA which has 4 points.
// - He has enough points to purchase a free product but since there is still
// no product in the order, reward button should not yet be highlighted.
// - Furthermore, clicking the reward product should not add it as reward product.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
// No item in the order, so reward button is off.
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("3.20");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order2: Generate 4 points for Test Partner CCC.
// - Reference: Order2_CCC
// - But set Test Partner BBB first as the customer.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner BBB");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "4.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.customerIs("Test Partner CCC");
PosLoyalty.check.orderTotalIs("12.80");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// Order3: Generate 3 points for Test Partner BBB.
// - Reference: Order3_BBB
// - But set Test Partner CCC first as the customer.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.exec.addOrderline("Whiteboard Pen", "3");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner BBB");
PosLoyalty.check.customerIs("Test Partner BBB");
PosLoyalty.check.orderTotalIs("9.60");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order4: Should not have reward because the customer will be removed.
// - Reference: Order4_no_reward
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
ProductScreen.do.clickPartnerButton();
// This deselects the customer.
PosLoyalty.do.unselectPartner();
PosLoyalty.check.customerIs("Customer");
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order2: Consumes points to get free product.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
// At this point, Test Partner AAA has 4 points.
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
return getSteps();
}
});
// Order3: Generate 4 points.
// - Initially gets free product, but was removed automatically by changing the
// number of items to zero.
// - It's impossible to checked here if the free product reward is really removed
// so we check in the backend the number of orders that consumed the reward.
ProductScreen.exec.addOrderline("Whiteboard Pen", "4");
PosLoyalty.check.orderTotalIs("12.80");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.pressNumpad("⌫");
// At this point, the reward line should have been automatically removed
// because there is not enough points to purchase it. Unfortunately, we
// can't check that here.
PosLoyalty.check.orderTotalIs("0.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "4.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
registry
.category("web_tour.tours")
.add("PosLoyaltyLoyaltyProgram3", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
// Generates 10.2 points and use points to get the reward product with zero sale price
ProductScreen.exec.addOrderline('Desk Organizer', '2');
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer('Test Partner AAA');
// At this point, the free_product program is triggered.
// The reward button should be highlighted.
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.hasRewardLine('Free Product - Whiteboard Pen', '0.0', '1.00');
PosLoyalty.check.orderTotalIs('10.2');
PosLoyalty.exec.finalizeOrder('Cash', '10.2');
PosLoyalty.check.orderTotalIs("12.80");
PosLoyalty.exec.finalizeOrder("Cash", "20");
return getSteps();
}
});
return getSteps();
},
});
registry.category("web_tour.tours").add("PosLoyaltyLoyaltyProgram2", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.clickHomeCategory();
// Order1: Immediately set the customer to Test Partner AAA which has 4 points.
// - He has enough points to purchase a free product but since there is still
// no product in the order, reward button should not yet be highlighted.
// - Furthermore, clicking the reward product should not add it as reward product.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
// No item in the order, so reward button is off.
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("3.20");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order2: Generate 4 points for Test Partner CCC.
// - Reference: Order2_CCC
// - But set Test Partner BBB first as the customer.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner BBB");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "2.00");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "3.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "4.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.customerIs("Test Partner CCC");
PosLoyalty.check.orderTotalIs("12.80");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// Order3: Generate 3 points for Test Partner BBB.
// - Reference: Order3_BBB
// - But set Test Partner CCC first as the customer.
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.exec.addOrderline("Whiteboard Pen", "3");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner BBB");
PosLoyalty.check.customerIs("Test Partner BBB");
PosLoyalty.check.orderTotalIs("9.60");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Order4: Should not have reward because the customer will be removed.
// - Reference: Order4_no_reward
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
ProductScreen.check.selectedOrderlineHas("Whiteboard Pen", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner CCC");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
ProductScreen.do.clickPartnerButton();
// This deselects the customer.
PosLoyalty.do.unselectPartner();
PosLoyalty.check.customerIs("Customer");
PosLoyalty.check.orderTotalIs("6.40");
PosLoyalty.exec.finalizeOrder("Cash", "10");
return getSteps();
},
});
registry.category("web_tour.tours").add("PosLoyaltyLoyaltyProgram3", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
// Generates 10.2 points and use points to get the reward product with zero sale price
ProductScreen.exec.addOrderline("Desk Organizer", "2");
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("Test Partner AAA");
// At this point, the free_product program is triggered.
// The reward button should be highlighted.
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "0.0", "1.00");
PosLoyalty.check.orderTotalIs("10.2");
PosLoyalty.exec.finalizeOrder("Cash", "10.2");
return getSteps();
},
});
@@ -6,205 +6,195 @@ import { SelectionPopup } from "@point_of_sale/../tests/tours/helpers/SelectionP
import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils";
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("PosLoyaltyFreeProductTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
registry
.category("web_tour.tours")
.add("PosLoyaltyFreeProductTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.exec.addOrderline("Desk Organizer", "2");
// At this point, the free_product program is triggered.
// The reward button should be highlighted.
PosLoyalty.check.isRewardButtonHighlighted(true);
// Since the reward button is highlighted, clicking the reward product should be added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-5.10", "1.00");
// In the succeeding 2 clicks on the product, it is considered as a regular product.
// In the third click, the product will be added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "6.00");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-10.20", "2.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("25.50");
// Finalize order that consumed a reward.
PosLoyalty.exec.finalizeOrder("Cash", "30");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "1.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "2.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-5.10", "1.00");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "0.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "1.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "2.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
// Finalize order but without the reward.
// This step is important. When syncing the order, no reward should be synced.
PosLoyalty.check.orderTotalIs("10.20");
PosLoyalty.exec.finalizeOrder("Cash", "20");
ProductScreen.exec.addOrderline("Magnetic Board", "2");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
ProductScreen.do.clickOrderline("Magnetic Board", "3.00");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "3.00");
ProductScreen.do.pressNumpad("6");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "6.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-6.40", "2.00");
// Finalize order that consumed a reward.
PosLoyalty.check.orderTotalIs("11.88");
PosLoyalty.exec.finalizeOrder("Cash", "20");
ProductScreen.exec.addOrderline("Magnetic Board", "6");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickOrderline("Magnetic Board", "6.00");
ProductScreen.do.pressNumpad("Backspace");
// At this point, the reward should have been removed.
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "0.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "1.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "2.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("5.94");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Promotion: 2 items of shelves, get desk_pad/monitor_stand free
// This is the 5th order.
ProductScreen.do.clickDisplayedProduct("Wall Shelf Unit");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Small Shelf");
ProductScreen.check.selectedOrderlineHas("Small Shelf", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
// Click reward product. Should be automatically added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Pad");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product", "-1.98", "1.00");
// Remove the reward line. The next steps will check if cashier
// can select from the different reward products.
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("Backspace");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - [Desk Pad, Monitor Stand]");
SelectionPopup.check.hasSelectionItem("Monitor Stand");
SelectionPopup.check.hasSelectionItem("Desk Pad");
SelectionPopup.do.clickItem("Desk Pad");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product", "-1.98", "1.00");
ProductScreen.do.pressNumpad("Backspace");
ProductScreen.do.pressNumpad("Backspace");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - [Desk Pad, Monitor Stand]");
SelectionPopup.check.hasSelectionItem("Monitor Stand");
SelectionPopup.check.hasSelectionItem("Desk Pad");
SelectionPopup.do.clickItem("Monitor Stand");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.00", "3.19");
PosLoyalty.check.hasRewardLine("Free Product", "-3.19", "1.00");
PosLoyalty.check.orderTotalIs("4.81");
PosLoyalty.exec.finalizeOrder("Cash", "10");
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
return getSteps();
}
});
ProductScreen.exec.addOrderline("Desk Organizer", "2");
registry
.category("web_tour.tours")
.add("PosLoyaltyFreeProductTour2", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("AAA Partner");
ProductScreen.exec.addOrderline("Test Product A", "1");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("Free Product - Test Product A");
PosLoyalty.check.hasRewardLine("Free Product - Test Product A", "-11.50", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
return getSteps();
}
});
// At this point, the free_product program is triggered.
// The reward button should be highlighted.
PosLoyalty.check.isRewardButtonHighlighted(true);
// Since the reward button is highlighted, clicking the reward product should be added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-5.10", "1.00");
// In the succeeding 2 clicks on the product, it is considered as a regular product.
// In the third click, the product will be added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "6.00");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-10.20", "2.00");
registry
.category("web_tour.tours")
.add("PosLoyaltySpecificDiscountTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickDisplayedProduct('Test Product A');
ProductScreen.check.selectedOrderlineHas('Test Product A', '1.00', '40.00');
ProductScreen.do.clickDisplayedProduct('Test Product B');
ProductScreen.check.selectedOrderlineHas('Test Product B', '1.00', '40.00');
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("$ 10 per order on specific products");
PosLoyalty.check.hasRewardLine('$ 10 per order on specific products', '-10.00', '1.00');
PosLoyalty.check.orderTotalIs('60.00');
return getSteps();
}
});
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("25.50");
// Finalize order that consumed a reward.
PosLoyalty.exec.finalizeOrder("Cash", "30");
registry
.category("web_tour.tours")
.add("PosLoyaltySpecificDiscountWithFreeProductTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "1.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "2.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-5.10", "1.00");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "0.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "1.00");
ProductScreen.do.clickDisplayedProduct("Desk Organizer");
ProductScreen.check.selectedOrderlineHas("Desk Organizer", "2.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
// Finalize order but without the reward.
// This step is important. When syncing the order, no reward should be synced.
PosLoyalty.check.orderTotalIs("10.20");
PosLoyalty.exec.finalizeOrder("Cash", "20");
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.exec.addOrderline("Magnetic Board", "2");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
ProductScreen.do.clickOrderline("Magnetic Board", "3.00");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "3.00");
ProductScreen.do.pressNumpad("6");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "6.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - Whiteboard Pen");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-6.40", "2.00");
// Finalize order that consumed a reward.
PosLoyalty.check.orderTotalIs("11.88");
PosLoyalty.exec.finalizeOrder("Cash", "20");
ProductScreen.do.clickDisplayedProduct('Test Product A');
ProductScreen.do.clickDisplayedProduct('Test Product C');
PosLoyalty.check.orderTotalIs('130.00');
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.clickRewardButton();
PosLoyalty.check.orderTotalIs('130.00');
return getSteps();
}
});
ProductScreen.exec.addOrderline("Magnetic Board", "6");
ProductScreen.do.clickDisplayedProduct("Whiteboard Pen");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
ProductScreen.do.clickOrderline("Magnetic Board", "6.00");
ProductScreen.do.pressNumpad("⌫");
// At this point, the reward should have been removed.
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "0.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "1.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "2.00");
ProductScreen.do.clickDisplayedProduct("Magnetic Board");
ProductScreen.check.selectedOrderlineHas("Magnetic Board", "3.00");
PosLoyalty.check.hasRewardLine("Free Product - Whiteboard Pen", "-3.20", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.orderTotalIs("5.94");
PosLoyalty.exec.finalizeOrder("Cash", "10");
// Promotion: 2 items of shelves, get desk_pad/monitor_stand free
// This is the 5th order.
ProductScreen.do.clickDisplayedProduct("Wall Shelf Unit");
ProductScreen.check.selectedOrderlineHas("Wall Shelf Unit", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.do.clickDisplayedProduct("Small Shelf");
ProductScreen.check.selectedOrderlineHas("Small Shelf", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
// Click reward product. Should be automatically added as reward.
ProductScreen.do.clickDisplayedProduct("Desk Pad");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product", "-1.98", "1.00");
// Remove the reward line. The next steps will check if cashier
// can select from the different reward products.
ProductScreen.do.pressNumpad("⌫");
ProductScreen.do.pressNumpad("⌫");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - [Desk Pad, Monitor Stand]");
SelectionPopup.check.hasSelectionItem("Monitor Stand");
SelectionPopup.check.hasSelectionItem("Desk Pad");
SelectionPopup.do.clickItem("Desk Pad");
PosLoyalty.check.isRewardButtonHighlighted(false);
PosLoyalty.check.hasRewardLine("Free Product", "-1.98", "1.00");
ProductScreen.do.pressNumpad("⌫");
ProductScreen.do.pressNumpad("⌫");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.claimReward("Free Product - [Desk Pad, Monitor Stand]");
SelectionPopup.check.hasSelectionItem("Monitor Stand");
SelectionPopup.check.hasSelectionItem("Desk Pad");
SelectionPopup.do.clickItem("Monitor Stand");
PosLoyalty.check.isRewardButtonHighlighted(false);
ProductScreen.check.selectedOrderlineHas("Monitor Stand", "1.00", "3.19");
PosLoyalty.check.hasRewardLine("Free Product", "-3.19", "1.00");
PosLoyalty.check.orderTotalIs("4.81");
PosLoyalty.exec.finalizeOrder("Cash", "10");
return getSteps();
},
});
registry.category("web_tour.tours").add("PosLoyaltyFreeProductTour2", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("AAA Partner");
ProductScreen.exec.addOrderline("Test Product A", "1");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("Free Product - Test Product A");
PosLoyalty.check.hasRewardLine("Free Product - Test Product A", "-11.50", "1.00");
PosLoyalty.check.isRewardButtonHighlighted(false);
return getSteps();
},
});
registry.category("web_tour.tours").add("PosLoyaltySpecificDiscountTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickDisplayedProduct("Test Product A");
ProductScreen.check.selectedOrderlineHas("Test Product A", "1.00", "40.00");
ProductScreen.do.clickDisplayedProduct("Test Product B");
ProductScreen.check.selectedOrderlineHas("Test Product B", "1.00", "40.00");
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("$ 10 per order on specific products");
PosLoyalty.check.hasRewardLine("$ 10 per order on specific products", "-10.00", "1.00");
PosLoyalty.check.orderTotalIs("60.00");
return getSteps();
},
});
registry.category("web_tour.tours").add("PosLoyaltySpecificDiscountWithFreeProductTour", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickDisplayedProduct("Test Product A");
ProductScreen.do.clickDisplayedProduct("Test Product C");
PosLoyalty.check.orderTotalIs("130.00");
PosLoyalty.check.isRewardButtonHighlighted(true);
PosLoyalty.do.clickRewardButton();
PosLoyalty.check.orderTotalIs("130.00");
return getSteps();
},
});
@@ -6,277 +6,261 @@ import { SelectionPopup } from "@point_of_sale/../tests/tours/helpers/SelectionP
import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils";
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add("PosLoyaltyTour1", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 1 ---
// Generate coupons for PosLoyaltyTour2.
startSteps();
registry
.category("web_tour.tours")
.add("PosLoyaltyTour1", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 1 ---
// Generate coupons for PosLoyaltyTour2.
startSteps();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
// basic order
// just accept the automatically applied promo program
// applied programs:
// - on cheapest product
ProductScreen.exec.addOrderline("Whiteboard Pen", "5");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.88");
PosLoyalty.do.selectRewardLine("on the cheapest product");
PosLoyalty.check.orderTotalIs("13.12");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// basic order
// just accept the automatically applied promo program
// applied programs:
// - on cheapest product
ProductScreen.exec.addOrderline("Whiteboard Pen", "5");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.88");
PosLoyalty.do.selectRewardLine("on the cheapest product");
PosLoyalty.check.orderTotalIs("13.12");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// remove the reward from auto promo program
// no applied programs
ProductScreen.exec.addOrderline("Whiteboard Pen", "6");
PosLoyalty.check.hasRewardLine("on the cheapest product", "-2.88");
PosLoyalty.check.orderTotalIs("16.32");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.orderTotalIs("19.2");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// remove the reward from auto promo program
// no applied programs
ProductScreen.exec.addOrderline("Whiteboard Pen", "6");
PosLoyalty.check.hasRewardLine("on the cheapest product", "-2.88");
PosLoyalty.check.orderTotalIs("16.32");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.orderTotalIs("19.2");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// order with coupon code from coupon program
// applied programs:
// - coupon program
ProductScreen.exec.addOrderline("Desk Organizer", "9");
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.orderTotalIs("45.90");
PosLoyalty.do.enterCode("invalid_code");
PosLoyalty.check.notificationMessageContains("invalid_code");
PosLoyalty.do.enterCode("1234");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-15.30");
PosLoyalty.exec.finalizeOrder("Cash", "50");
// order with coupon code from coupon program
// applied programs:
// - coupon program
ProductScreen.exec.addOrderline("Desk Organizer", "9");
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.orderTotalIs("45.90");
PosLoyalty.do.enterCode("invalid_code");
PosLoyalty.check.notificationMessageContains("invalid_code");
PosLoyalty.do.enterCode("1234");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-15.30");
PosLoyalty.exec.finalizeOrder("Cash", "50");
// Use coupon but eventually remove the reward
// applied programs:
// - on cheapest product
ProductScreen.exec.addOrderline("Letter Tray", "4");
ProductScreen.exec.addOrderline("Desk Organizer", "9");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.75");
PosLoyalty.check.orderTotalIs("62.27");
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-15.30");
PosLoyalty.check.orderTotalIs("46.97");
PosLoyalty.exec.removeRewardLine("Free Product");
PosLoyalty.check.orderTotalIs("62.27");
PosLoyalty.exec.finalizeOrder("Cash", "90");
// Use coupon but eventually remove the reward
// applied programs:
// - on cheapest product
ProductScreen.exec.addOrderline("Letter Tray", "4");
ProductScreen.exec.addOrderline("Desk Organizer", "9");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.75");
PosLoyalty.check.orderTotalIs("62.27");
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-15.30");
PosLoyalty.check.orderTotalIs("46.97");
PosLoyalty.exec.removeRewardLine("Free Product");
PosLoyalty.check.orderTotalIs("62.27");
PosLoyalty.exec.finalizeOrder("Cash", "90");
// specific product discount
// applied programs:
// - on cheapest product
// - on specific products
ProductScreen.exec.addOrderline("Magnetic Board", "10"); // 1.98
ProductScreen.exec.addOrderline("Desk Organizer", "3"); // 5.1
ProductScreen.exec.addOrderline("Letter Tray", "4"); // 4.8 tax 10%
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-1.78");
PosLoyalty.check.orderTotalIs("54.44");
PosLoyalty.do.enterCode("promocode");
PosLoyalty.check.hasRewardLine("50% on specific products", "-16.66"); // 17.55 - 1.78*0.5
PosLoyalty.check.orderTotalIs("37.78");
PosLoyalty.exec.finalizeOrder("Cash", "50");
return getSteps();
},
});
// specific product discount
// applied programs:
// - on cheapest product
// - on specific products
ProductScreen.exec.addOrderline("Magnetic Board", "10"); // 1.98
ProductScreen.exec.addOrderline("Desk Organizer", "3"); // 5.1
ProductScreen.exec.addOrderline("Letter Tray", "4"); // 4.8 tax 10%
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-1.78");
PosLoyalty.check.orderTotalIs("54.44");
PosLoyalty.do.enterCode("promocode");
PosLoyalty.check.hasRewardLine("50% on specific products", "-16.66"); // 17.55 - 1.78*0.5
PosLoyalty.check.orderTotalIs("37.78");
PosLoyalty.exec.finalizeOrder("Cash", "50");
return getSteps();
}
});
registry.category("web_tour.tours").add("PosLoyaltyTour2", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 2 ---
// Using the coupons generated from PosLoyaltyTour1.
startSteps();
ProductScreen.do.clickHomeCategory();
registry
.category("web_tour.tours")
.add("PosLoyaltyTour2", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 2 ---
// Using the coupons generated from PosLoyaltyTour1.
startSteps();
// Test that global discount and cheapest product discounts can be accumulated.
// Applied programs:
// - global discount
// - on cheapest discount
ProductScreen.exec.addOrderline("Desk Organizer", "10"); // 5.1
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
ProductScreen.exec.addOrderline("Letter Tray", "4"); // 4.8 tax 10%
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.75");
PosLoyalty.do.enterCode("123456");
PosLoyalty.check.hasRewardLine("10% on your order", "-5.10");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.64");
PosLoyalty.check.orderTotalIs("60.63"); //SUBTOTAL
PosLoyalty.exec.finalizeOrder("Cash", "70");
ProductScreen.do.clickHomeCategory();
// Scanning coupon twice.
// Also apply global discount on top of free product to check if the
// calculated discount is correct.
// Applied programs:
// - coupon program (free product)
// - global discount
// - on cheapest discount
ProductScreen.exec.addOrderline("Desk Organizer", "11"); // 5.1 per item
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.59");
PosLoyalty.check.orderTotalIs("51.51");
// add global discount and the discount will be replaced
PosLoyalty.do.enterCode("345678");
PosLoyalty.check.hasRewardLine("10% on your order", "-5.15");
// add free product coupon (for qty=11, free=4)
// the discount should change after having free products
// it should go back to cheapest discount as it is higher
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-20.40");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.59");
// set quantity to 18
// free qty stays the same since the amount of points on the card only allows for 4 free products
ProductScreen.do.pressNumpad("⌫", "8");
PosLoyalty.check.hasRewardLine("10% on your order", "-6.68");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-20.40");
// scan the code again and check notification
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.orderTotalIs("60.13");
PosLoyalty.exec.finalizeOrder("Cash", "65");
// Test that global discount and cheapest product discounts can be accumulated.
// Applied programs:
// - global discount
// - on cheapest discount
ProductScreen.exec.addOrderline("Desk Organizer", "10"); // 5.1
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
ProductScreen.exec.addOrderline("Letter Tray", "4"); // 4.8 tax 10%
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.75");
PosLoyalty.do.enterCode("123456");
PosLoyalty.check.hasRewardLine("10% on your order", "-5.10");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.64");
PosLoyalty.check.orderTotalIs("60.63"); //SUBTOTAL
PosLoyalty.exec.finalizeOrder("Cash", "70");
// Specific products discount (with promocode) and free product (1357)
// Applied programs:
// - discount on specific products
// - free product
ProductScreen.exec.addOrderline("Desk Organizer", "6"); // 5.1 per item
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.do.enterCode("promocode");
PosLoyalty.check.hasRewardLine("50% on specific products", "-15.30");
PosLoyalty.do.enterCode("1357");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-10.20");
PosLoyalty.check.hasRewardLine("50% on specific products", "-10.20");
PosLoyalty.check.orderTotalIs("10.20");
PosLoyalty.exec.finalizeOrder("Cash", "20");
// Scanning coupon twice.
// Also apply global discount on top of free product to check if the
// calculated discount is correct.
// Applied programs:
// - coupon program (free product)
// - global discount
// - on cheapest discount
ProductScreen.exec.addOrderline("Desk Organizer", "11"); // 5.1 per item
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.59");
PosLoyalty.check.orderTotalIs("51.51");
// add global discount and the discount will be replaced
PosLoyalty.do.enterCode("345678");
PosLoyalty.check.hasRewardLine("10% on your order", "-5.15");
// add free product coupon (for qty=11, free=4)
// the discount should change after having free products
// it should go back to cheapest discount as it is higher
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-20.40");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-4.59");
// set quantity to 18
// free qty stays the same since the amount of points on the card only allows for 4 free products
ProductScreen.do.pressNumpad("Backspace 8");
PosLoyalty.check.hasRewardLine("10% on your order", "-6.68");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-20.40");
// scan the code again and check notification
PosLoyalty.do.enterCode("5678");
PosLoyalty.check.orderTotalIs("60.13");
PosLoyalty.exec.finalizeOrder("Cash", "65");
// Check reset program
// Enter two codes and reset the programs.
// The codes should be checked afterwards. They should return to new.
// Applied programs:
// - cheapest product
ProductScreen.exec.addOrderline("Monitor Stand", "6"); // 3.19 per item
PosLoyalty.do.enterCode("098765");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.87");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.63");
PosLoyalty.check.orderTotalIs("14.64");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.91");
PosLoyalty.check.orderTotalIs("17.23");
PosLoyalty.do.resetActivePrograms();
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.87");
PosLoyalty.check.orderTotalIs("16.27");
PosLoyalty.exec.finalizeOrder("Cash", "20");
return getSteps();
},
});
// Specific products discount (with promocode) and free product (1357)
// Applied programs:
// - discount on specific products
// - free product
ProductScreen.exec.addOrderline("Desk Organizer", "6"); // 5.1 per item
PosLoyalty.check.hasRewardLine("on the cheapest product", "-4.59");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.do.enterCode("promocode");
PosLoyalty.check.hasRewardLine("50% on specific products", "-15.30");
PosLoyalty.do.enterCode("1357");
PosLoyalty.check.hasRewardLine("Free Product - Desk Organizer", "-10.20");
PosLoyalty.check.hasRewardLine("50% on specific products", "-10.20");
PosLoyalty.check.orderTotalIs("10.20");
PosLoyalty.exec.finalizeOrder("Cash", "20");
registry.category("web_tour.tours").add("PosLoyaltyTour3", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 3 ---
// Check reset program
// Enter two codes and reset the programs.
// The codes should be checked afterwards. They should return to new.
// Applied programs:
// - cheapest product
ProductScreen.exec.addOrderline("Monitor Stand", "6"); // 3.19 per item
PosLoyalty.do.enterCode("098765");
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.87");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.63");
PosLoyalty.check.orderTotalIs("14.64");
PosLoyalty.exec.removeRewardLine("90% on the cheapest product");
PosLoyalty.check.hasRewardLine("10% on your order", "-1.91");
PosLoyalty.check.orderTotalIs("17.23");
PosLoyalty.do.resetActivePrograms();
PosLoyalty.check.hasRewardLine("90% on the cheapest product", "-2.87");
PosLoyalty.check.orderTotalIs("16.27");
PosLoyalty.exec.finalizeOrder("Cash", "20");
return getSteps();
}
});
startSteps();
registry
.category("web_tour.tours")
.add("PosLoyaltyTour3", {
test: true,
url: "/pos/web",
steps: () => {
// --- PoS Loyalty Tour Basic Part 3 ---
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
startSteps();
ProductScreen.do.clickDisplayedProduct("Promo Product");
PosLoyalty.check.orderTotalIs("34.50");
ProductScreen.do.clickDisplayedProduct("Product B");
PosLoyalty.check.hasRewardLine("100% on specific products", "25.00");
ProductScreen.do.clickDisplayedProduct("Product A");
PosLoyalty.check.hasRewardLine("100% on specific products", "15.00");
PosLoyalty.check.orderTotalIs("34.50");
ProductScreen.do.clickDisplayedProduct("Product A");
PosLoyalty.check.hasRewardLine("100% on specific products", "21.82");
PosLoyalty.check.hasRewardLine("100% on specific products", "18.18");
PosLoyalty.check.orderTotalIs("49.50");
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
return getSteps();
},
});
ProductScreen.do.clickDisplayedProduct("Promo Product");
PosLoyalty.check.orderTotalIs("34.50");
ProductScreen.do.clickDisplayedProduct("Product B");
PosLoyalty.check.hasRewardLine("100% on specific products", "25.00");
ProductScreen.do.clickDisplayedProduct("Product A");
PosLoyalty.check.hasRewardLine("100% on specific products", "15.00");
PosLoyalty.check.orderTotalIs("34.50");
ProductScreen.do.clickDisplayedProduct("Product A");
PosLoyalty.check.hasRewardLine("100% on specific products", "21.82");
PosLoyalty.check.hasRewardLine("100% on specific products", "18.18");
PosLoyalty.check.orderTotalIs("49.50");
registry.category("web_tour.tours").add("PosLoyaltyTour4", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
return getSteps();
}
});
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
registry
.category("web_tour.tours")
.add("PosLoyaltyTour4", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.exec.addOrderline("Test Product 1", "1");
ProductScreen.exec.addOrderline("Test Product 2", "1");
ProductScreen.do.selectPriceList("Public Pricelist");
PosLoyalty.do.enterCode("abcda");
PosLoyalty.check.orderTotalIs("0.00");
ProductScreen.do.selectPriceList("Test multi-currency");
PosLoyalty.check.orderTotalIs("0.00");
return getSteps();
},
});
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
registry.category("web_tour.tours").add("PosCouponTour5", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.exec.addOrderline("Test Product 1", "1");
ProductScreen.exec.addOrderline("Test Product 2", "1");
ProductScreen.do.selectPriceList("Public Pricelist");
PosLoyalty.do.enterCode("abcda");
PosLoyalty.check.orderTotalIs("0.00");
ProductScreen.do.selectPriceList("Test multi-currency");
PosLoyalty.check.orderTotalIs("0.00");
return getSteps();
}
});
ProductScreen.do.clickHomeCategory();
registry
.category("web_tour.tours")
.add("PosCouponTour5", {
test: true,
url: "/pos/web",
steps: () => {
startSteps();
ProductScreen.do.clickHomeCategory();
ProductScreen.exec.addOrderline("Test Product 1", "1.00", "100");
PosLoyalty.do.clickDiscountButton();
PosLoyalty.do.clickConfirmButton();
ProductScreen.check.totalAmountIs("92.00");
return getSteps();
}
});
ProductScreen.exec.addOrderline("Test Product 1", "1.00", "100");
PosLoyalty.do.clickDiscountButton();
PosLoyalty.do.clickConfirmButton();
ProductScreen.check.totalAmountIs("92.00");
return getSteps();
},
});
//transform the last tour to match the new format
registry
.category("web_tour.tours")
.add("PosLoyaltyTour6", {
test: true,
url: "/pos/web",
steps: () => {
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
registry.category("web_tour.tours").add("PosLoyaltyTour6", {
test: true,
url: "/pos/web",
steps: () => {
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer('AAA Partner');
ProductScreen.do.clickDisplayedProduct('Test Product A');
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("$ 1 per point on your order");
ProductScreen.check.totalAmountIs('138.50');
return getSteps();
}
});
ProductScreen.do.clickPartnerButton();
ProductScreen.do.clickCustomer("AAA Partner");
ProductScreen.do.clickDisplayedProduct("Test Product A");
PosLoyalty.do.clickRewardButton();
SelectionPopup.do.clickItem("$ 1 per point on your order");
ProductScreen.check.totalAmountIs("138.50");
return getSteps();
},
});
registry
.category("web_tour.tours")
.add("PosLoyaltyTour7", {
test: true,
url: "/pos/web",
steps: () => {
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
registry.category("web_tour.tours").add("PosLoyaltyTour7", {
test: true,
url: "/pos/web",
steps: () => {
ProductScreen.do.confirmOpeningPopup();
ProductScreen.do.clickHomeCategory();
ProductScreen.exec.addOrderline('Test Product', '1');
PosLoyalty.check.orderTotalIs('100');
PosLoyalty.do.enterCode('abcda');
PosLoyalty.check.orderTotalIs('90');
return getSteps();
}
});
ProductScreen.exec.addOrderline("Test Product", "1");
PosLoyalty.check.orderTotalIs("100");
PosLoyalty.do.enterCode("abcda");
PosLoyalty.check.orderTotalIs("90");
return getSteps();
},
});
@@ -193,7 +193,7 @@ class Execute {
removeRewardLine(name) {
return [
...this.do.selectRewardLine(name),
...ProductScreen.do.pressNumpad("Backspace"),
...ProductScreen.do.pressNumpad("⌫"),
...Chrome.do.confirmPopup(),
];
}
@@ -8,121 +8,119 @@ import { ProductScreen } from "@pos_restaurant/../tests/tours/helpers/ProductScr
import { getSteps, startSteps } from "@point_of_sale/../tests/tours/helpers/utils";
import { registry } from "@web/core/registry";
registry
.category("web_tour.tours")
.add("FloorScreenTour", {
test: true,
url: "/pos/ui",
steps: () => {
// signal to start generating steps
// when finished, steps can be taken from getSteps
startSteps();
// check floors if they contain their corresponding tables
FloorScreen.check.selectedFloorIs("Main Floor");
FloorScreen.check.hasTable("2");
FloorScreen.check.hasTable("4");
FloorScreen.check.hasTable("5");
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.check.hasTable("1");
// clicking table in active mode does not open product screen
// instead, table is selected
FloorScreen.do.clickEdit();
FloorScreen.do.clickTable("3");
FloorScreen.check.selectedTableIs("3");
FloorScreen.do.clickTable("1");
FloorScreen.check.selectedTableIs("1");
// test add table
FloorScreen.do.clickFloor("Main Floor");
FloorScreen.do.clickAddTable();
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.clickRename();
TextInputPopup.check.isShown();
TextInputPopup.do.inputText("100");
TextInputPopup.do.clickConfirm();
FloorScreen.do.clickTable("100");
FloorScreen.check.selectedTableIs("100");
// test duplicate table
FloorScreen.do.clickDuplicate();
// the name is the first number available on the floor
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.clickRename();
TextInputPopup.check.isShown();
TextInputPopup.do.inputText("1111");
TextInputPopup.do.clickConfirm();
FloorScreen.do.clickTable("1111");
FloorScreen.check.selectedTableIs("1111");
// switch floor, switch back and check if
// the new tables are still there
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.check.hasTable("1");
//test duplicate multiple tables
FloorScreen.do.clickTable("1");
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.ctrlClickTable("3");
FloorScreen.check.selectedTableIs("3");
FloorScreen.do.clickDuplicate();
FloorScreen.check.selectedTableIs("2");
FloorScreen.check.selectedTableIs("4");
//test delete multiple tables
FloorScreen.do.clickTrash();
Chrome.do.confirmPopup();
FloorScreen.do.clickFloor("Main Floor");
FloorScreen.check.hasTable("2");
FloorScreen.check.hasTable("4");
FloorScreen.check.hasTable("5");
FloorScreen.check.hasTable("100");
FloorScreen.check.hasTable("1111");
// test delete table
FloorScreen.do.clickTable("2");
FloorScreen.check.selectedTableIs("2");
FloorScreen.do.clickTrash();
Chrome.do.confirmPopup();
// change number of seats
FloorScreen.do.clickTable("4");
FloorScreen.check.selectedTableIs("4");
FloorScreen.do.clickSeats();
NumberPopup.do.pressNumpad("Backspace 9");
NumberPopup.do.fillPopupValue("9");
NumberPopup.check.inputShownIs("9");
NumberPopup.do.clickConfirm();
FloorScreen.check.tableSeatIs("4", "9");
// change number of seat when the input is already selected
FloorScreen.do.clickTable("4");
FloorScreen.check.selectedTableIs("4");
FloorScreen.do.clickSeats();
NumberPopup.do.enterValue("15");
NumberPopup.check.inputShownIs("15");
NumberPopup.do.clickConfirm();
FloorScreen.check.tableSeatIs("4", "15");
// change shape
FloorScreen.do.clickTable("4");
FloorScreen.do.changeShapeTo("round");
// Opening product screen in main floor should go back to main floor
FloorScreen.do.closeEdit();
FloorScreen.check.tableIsNotSelected("4");
FloorScreen.do.clickTable("4");
ProductScreen.check.isShown();
Chrome.do.backToFloor();
// Opening product screen in second floor should go back to second floor
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.do.clickTable("3");
return getSteps();
}
});
registry.category("web_tour.tours").add("FloorScreenTour", {
test: true,
url: "/pos/ui",
steps: () => {
// signal to start generating steps
// when finished, steps can be taken from getSteps
startSteps();
// check floors if they contain their corresponding tables
FloorScreen.check.selectedFloorIs("Main Floor");
FloorScreen.check.hasTable("2");
FloorScreen.check.hasTable("4");
FloorScreen.check.hasTable("5");
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.check.hasTable("1");
// clicking table in active mode does not open product screen
// instead, table is selected
FloorScreen.do.clickEdit();
FloorScreen.do.clickTable("3");
FloorScreen.check.selectedTableIs("3");
FloorScreen.do.clickTable("1");
FloorScreen.check.selectedTableIs("1");
// test add table
FloorScreen.do.clickFloor("Main Floor");
FloorScreen.do.clickAddTable();
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.clickRename();
TextInputPopup.check.isShown();
TextInputPopup.do.inputText("100");
TextInputPopup.do.clickConfirm();
FloorScreen.do.clickTable("100");
FloorScreen.check.selectedTableIs("100");
// test duplicate table
FloorScreen.do.clickDuplicate();
// the name is the first number available on the floor
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.clickRename();
TextInputPopup.check.isShown();
TextInputPopup.do.inputText("1111");
TextInputPopup.do.clickConfirm();
FloorScreen.do.clickTable("1111");
FloorScreen.check.selectedTableIs("1111");
// switch floor, switch back and check if
// the new tables are still there
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.check.hasTable("1");
//test duplicate multiple tables
FloorScreen.do.clickTable("1");
FloorScreen.check.selectedTableIs("1");
FloorScreen.do.ctrlClickTable("3");
FloorScreen.check.selectedTableIs("3");
FloorScreen.do.clickDuplicate();
FloorScreen.check.selectedTableIs("2");
FloorScreen.check.selectedTableIs("4");
//test delete multiple tables
FloorScreen.do.clickTrash();
Chrome.do.confirmPopup();
FloorScreen.do.clickFloor("Main Floor");
FloorScreen.check.hasTable("2");
FloorScreen.check.hasTable("4");
FloorScreen.check.hasTable("5");
FloorScreen.check.hasTable("100");
FloorScreen.check.hasTable("1111");
// test delete table
FloorScreen.do.clickTable("2");
FloorScreen.check.selectedTableIs("2");
FloorScreen.do.clickTrash();
Chrome.do.confirmPopup();
// change number of seats
FloorScreen.do.clickTable("4");
FloorScreen.check.selectedTableIs("4");
FloorScreen.do.clickSeats();
NumberPopup.do.pressNumpad("⌫ 9");
NumberPopup.do.fillPopupValue("9");
NumberPopup.check.inputShownIs("9");
NumberPopup.do.clickConfirm();
FloorScreen.check.tableSeatIs("4", "9");
// change number of seat when the input is already selected
FloorScreen.do.clickTable("4");
FloorScreen.check.selectedTableIs("4");
FloorScreen.do.clickSeats();
NumberPopup.do.enterValue("15");
NumberPopup.check.inputShownIs("15");
NumberPopup.do.clickConfirm();
FloorScreen.check.tableSeatIs("4", "15");
// change shape
FloorScreen.do.clickTable("4");
FloorScreen.do.changeShapeTo("round");
// Opening product screen in main floor should go back to main floor
FloorScreen.do.closeEdit();
FloorScreen.check.tableIsNotSelected("4");
FloorScreen.do.clickTable("4");
ProductScreen.check.isShown();
Chrome.do.backToFloor();
// Opening product screen in second floor should go back to second floor
FloorScreen.do.clickFloor("Second Floor");
FloorScreen.check.hasTable("3");
FloorScreen.do.clickTable("3");
return getSteps();
},
});
@@ -12,8 +12,6 @@ registry.category("web_tour.tours").add("RefundStayCurrentTableTour", {
test: true,
url: "/pos/ui",
steps: () => {
// signal to start generating steps
// when finished, steps can be taken from getSteps
startSteps();
ProductScreen.do.confirmOpeningPopup();
@@ -31,13 +29,13 @@ registry.category("web_tour.tours").add("RefundStayCurrentTableTour", {
PaymentScreen.do.clickValidate();
ReceiptScreen.do.clickNextOrder();
// Go to another table and refund one of the product
// Go to another table and refund one of the products
FloorScreen.do.clickTable("4");
ProductScreen.check.orderIsEmpty();
ProductScreen.do.clickRefund();
TicketScreen.do.selectOrder("-0001");
TicketScreen.do.clickOrderline("Coca-Cola");
TicketScreen.do.pressNumpad("2");
ProductScreen.do.pressNumpad("2");
TicketScreen.check.toRefundTextContains("To Refund: 2.00");
TicketScreen.do.confirmRefund();
ProductScreen.check.isShown();
@@ -50,7 +50,7 @@ class DoExt extends Do {
},
{
content: `click on +10 button`,
trigger: `.mode-button.add:contains('+10')`,
trigger: `div.numpad.row button.col:contains("+10")`,
},
{
content: `click on ok button`,
@@ -22,7 +22,7 @@ registry
ProductScreen.do.clickQuotationButton();
ProductScreen.do.selectFirstOrder();
ProductScreen.check.selectedOrderlineHas('Pizza Chicken', 9);
ProductScreen.do.pressNumpad('Qty 2'); // Change the quantity of the product to 2
ProductScreen.do.pressNumpad('Qty', '2'); // Change the quantity of the product to 2
ProductScreen.check.selectedOrderlineHas('Pizza Chicken', 2);
ProductScreen.do.clickPayButton();
PaymentScreen.do.clickPaymentMethod('Bank');
@@ -76,7 +76,7 @@ registry
ProductScreen.do.clickOrderline("Product A", "1");
ProductScreen.check.selectedOrderlineHas('Product A', '1.00');
ProductScreen.do.clickOrderline("Product B", "1");
ProductScreen.do.pressNumpad('Qty 0');
ProductScreen.do.pressNumpad("Qty", "0");
ProductScreen.check.selectedOrderlineHas('Product B', '0.00');
ProductScreen.do.clickPayButton();
PaymentScreen.do.clickPaymentMethod('Bank');
@@ -106,7 +106,7 @@ registry
TicketScreen.check.filterIs('Paid');
TicketScreen.do.selectOrder('-0001');
TicketScreen.do.clickOrderline('Down Payment');
TicketScreen.do.pressNumpad('1');
ProductScreen.do.pressNumpad('1');
TicketScreen.do.confirmRefund();
ProductScreen.do.clickPayButton();
PaymentScreen.do.clickPaymentMethod('Cash');