[REF] point_of_sale, pos*: remove PosComponent

*: pos_discount, pos_hr, pos_loyalty, pos_restaurant, pos_sale, pos_six

Previously, all components in the pos and related apps would inherit
from the PosComponent base component, this component contained a bunch
of methods that were as such available on every component in the pos
passively. In previous commits, a bunch of these methods have been moved
either to the pos store or to their own services, so that component
dependencies are explicit instead of every component having a clobbered
namespace and having access to everything implictly.

This commit factors out the last method of the PosComponent,
`setSyncStatus` and as such the PosComponent is now empty and can be
removed completely, as can the Gui singleton utility which was used to
access these methods from outside of components.

Components in the pos modules now inherit from LegacyComponent which
PosComponent extended. The end goal is to remove the use of
LegacyComponent as well, but currently it is still needed as components
in the pos modules make extensive use of `useListener` which requires
the shim for `this.el` provided by LegacyComponent. This is nonetheless
a first step in that direction.

This commit also removes some components that were used in the navbar as
they were very small and it made more sense to just have the behaviour
they implement directly in the navbar component or elsewhere. Most of
the CashMoveButton was moved to the CashMovePopup, the TicketButton has
so little behaviour that moving that behaviour to the navbar itself
makes sense.

closes odoo/odoo#112295

Related: odoo/enterprise#36860
Signed-off-by: Heinz Robin (rhe) <rhe@odoo.com>
This commit is contained in:
Samuel Degueldre
2023-02-09 18:07:23 +01:00
parent e745a7168a
commit 6d8ebdf829
103 changed files with 584 additions and 763 deletions
@@ -1,7 +1,7 @@
/** @odoo-module */
import { parse } from "web.field_utils";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { Transition } from "@web/core/transition";
import { Draggable } from "@point_of_sale/js/Misc/Draggable";
import { ConfirmPopup } from "@point_of_sale/js/Popups/ConfirmPopup";
@@ -10,7 +10,7 @@ import { useBus, useService } from "@web/core/utils/hooks";
import { useRef, useState } from "@odoo/owl";
export class DebugWidget extends PosComponent {
export class DebugWidget extends LegacyComponent {
static components = { Transition, Draggable };
static template = "point_of_sale.DebugWidget";
setup() {
@@ -3,7 +3,6 @@
import { registry } from "@web/core/registry";
import { odooExceptionTitleMap } from "@web/core/errors/error_dialogs";
import { ConnectionLostError, RPCError } from "@web/core/network/rpc_service";
import { GuiNotReadyError } from "@point_of_sale/js/Gui";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { ErrorTracebackPopup } from "@point_of_sale/js/Popups/ErrorTracebackPopup";
import { OfflineErrorPopup } from "@point_of_sale/js/Popups/OfflineErrorPopup";
@@ -62,12 +61,3 @@ function defaultErrorHandler(env, error, originalError) {
registry
.category("error_handlers")
.add("defaultErrorHandler", defaultErrorHandler, { sequence: 99 });
function guiNotReadyHandler(env, error, originalError) {
error = identifyError(originalError);
if (error instanceof GuiNotReadyError) {
console.error(originalError);
return true;
}
}
registry.category("error_handlers").add("guiNotReadyHandler", guiNotReadyHandler);
@@ -0,0 +1,98 @@
/** @odoo-module */
import { _t } from "@web/core/l10n/translation";
import { sprintf } from "@web/core/utils/strings";
import { renderToString } from "@web/core/utils/render";
import { useAutofocus, useService } from "@web/core/utils/hooks";
import { parseFloat, InvalidNumberError } from "@web/views/fields/parsers";
import { useState } from "@odoo/owl";
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
export class CashMovePopup extends AbstractAwaitablePopup {
static template = "point_of_sale.CashMovePopup";
setup() {
super.setup();
this.notification = useService("pos_notification");
this.popup = useService("popup");
this.state = useState({
/** @type {'in'|'out'} */
type: "out",
amount: "",
reason: "",
errorMessage: "",
});
this.amountInput = useAutofocus({ refName: "amountInput" });
}
async confirm() {
let amount;
try {
amount = parseFloat(this.state.amount);
} catch (err) {
if (!(err instanceof InvalidNumberError)) {
throw err;
}
this.state.errorMessage = this.env._t("Invalid amount");
return;
}
if (amount < 0) {
this.state.errorMessage = this.env._t("Insert a positive amount");
return;
}
const formattedAmount = this.env.pos.format_currency(amount);
if (!amount) {
this.notification.add(
sprintf(_t("Cash in/out of %s is ignored."), formattedAmount),
3000
);
return this.props.close();
}
const type = this.state.type;
const translatedType = _t(type);
const extras = { formattedAmount, translatedType };
const reason = this.state.reason.trim();
await this.rpc({
model: "pos.session",
method: "try_cash_in_out",
args: [[this.env.pos.pos_session.id], type, amount, reason, extras],
});
if (this.env.proxy.printer) {
const renderedReceipt = renderToString("point_of_sale.CashMoveReceipt", {
_receipt: {
type,
reason,
amount,
translatedType,
formattedAmount,
cashier: this.env.pos.get_cashier(),
company: this.env.pos.company,
},
});
const printResult = await this.env.proxy.printer.print_receipt(renderedReceipt);
if (!printResult.successful) {
this.popup.add(ErrorPopup, {
title: printResult.message.title,
body: printResult.message.body,
});
}
}
this.props.close();
this.notification.add(
sprintf(this.env._t("Successfully made a cash %s of %s."), type, formattedAmount),
3000
);
}
_onAmountKeypress(event) {
if (["-", "+"].includes(event.key)) {
event.preventDefault();
}
}
onClickButton(type) {
this.state.type = type;
this.state.errorMessage = "";
this.amountInput.el.focus();
}
}
@@ -0,0 +1,93 @@
.cash-move-popup {
top: 20% !important;
.input-amount {
display: flex;
flex-flow: row;
}
.input-type {
height: 40px;
line-height: 40px;
text-align: center;
border-radius: 2px;
padding: 0 12px;
margin-right: 10px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
border: solid 1px rgba(60,60,60,0.1);
background: rgba(0,0,0,0.05);
white-space: nowrap;
&.highlight {
background: $primary !important;
border: solid 1px #64AF8A !important;
color: white !important;
}
&.red-highlight {
background: #bd2222 !important;
border: solid 1px #bd2222 !important;
color: white !important;
}
input {
width: 100%;
min-height: auto;
text-align: right;
padding-right: 30px;
}
}
.input-field {
position: relative;
flex-grow: 1;
.currency {
position: absolute;
right: 10px;
top: 10px;
}
.left-currency {
position: absolute;
left: 10px;
top: 10px;
background-color: #fff;
padding-right: 8px;
}
}
textarea {
resize: none;
margin-top: 10px;
margin-bottom: 10px;
}
.error-message {
color: rgb(197, 52, 0);
text-align: left;
padding-left: 5px;
}
// FIXME POSREF increased selector specificity to override default style. Should just be "footer"
footer.cash-move.cash-move {
display: block;
width: calc(100% - 36px);
padding: 10px 18px 10px 18px;
.button.confirm {
float: left;
}
.button.cancel {
margin-right: 0;
}
}
}
.cash-move {
display: flex;
flex-flow: column;
}
@@ -6,14 +6,14 @@
<main class="body">
<div class="cash-move">
<div class="input-amount">
<span t-on-click="() => this.onClickButton('in')" class="input-type" t-att-class="{ highlight: state.inputType == 'in' }">
<span t-on-click="() => this.onClickButton('in')" class="input-type" t-att-class="{ highlight: state.type === 'in' }">
Cash In
</span>
<span t-on-click="() => this.onClickButton('out')" class="input-type" t-att-class="{ 'red-highlight': state.inputType == 'out' }">
<span t-on-click="() => this.onClickButton('out')" class="input-type" t-att-class="{ 'red-highlight': state.type === 'out' }">
Cash Out
</span>
<div class="input-field">
<input type="number" name="amount" t-model="state.inputAmount" t-ref="input-amount-ref" t-on-keypress="_onAmountKeypress"/>
<input type="number" name="amount" t-model="state.amount" t-ref="amountInput" t-on-keypress="_onAmountKeypress"/>
<t t-if="env.pos.currency.symbol.length > 1">
<span class="left-currency" t-esc="env.pos.currency.symbol" />
</t>
@@ -22,7 +22,7 @@
</t>
</div>
</div>
<textarea name="reason" t-model="state.inputReason" placeholder="Reason"></textarea>
<textarea name="reason" t-model="state.reason" placeholder="Reason"></textarea>
<span t-if="state.errorMessage" class="error-message">
<t t-esc="state.errorMessage" />
</span>
@@ -1,30 +1,28 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { usePos } from "@point_of_sale/app/pos_hook";
import { useService } from "@web/core/utils/hooks";
import { CashierName } from "@point_of_sale/js/ChromeWidgets/CashierName";
import { CashMoveButton } from "@point_of_sale/js/ChromeWidgets/CashMoveButton";
import { CustomerFacingDisplayButton } from "@point_of_sale/js/ChromeWidgets/CustomerFacingDisplayButton";
import { HeaderButton } from "@point_of_sale/js/ChromeWidgets/HeaderButton";
import { ProxyStatus } from "@point_of_sale/js/ChromeWidgets/ProxyStatus";
import { SaleDetailsButton } from "@point_of_sale/js/ChromeWidgets/SaleDetailsButton";
import { SyncNotification } from "@point_of_sale/js/ChromeWidgets/SyncNotification";
import { TicketButton } from "@point_of_sale/js/ChromeWidgets/TicketButton";
import { CashMovePopup } from "./cash_move_popup/cash_move_popup";
import { TicketScreen } from "@point_of_sale/js/Screens/TicketScreen/TicketScreen";
export class Navbar extends PosComponent {
export class Navbar extends LegacyComponent {
static template = "point_of_sale.Navbar";
static components = {
// FIXME POSREF remove some of these components
CashierName,
CashMoveButton,
CustomerFacingDisplayButton,
HeaderButton,
ProxyStatus,
SaleDetailsButton,
SyncNotification,
TicketButton,
};
static props = {
showCashMoveButton: Boolean,
@@ -32,8 +30,33 @@ export class Navbar extends PosComponent {
setup() {
this.pos = usePos();
this.debug = useService("debug");
this.popup = useService("popup");
}
get customerFacingDisplayButtonIsShown() {
return this.env.pos.config.iface_customer_facing_display;
}
onCashMoveButtonClick() {
this.popup.add(CashMovePopup);
}
onTicketButtonClick() {
if (this.isTicketScreenShown) {
this.pos.closeScreen();
} else {
this.pos.showScreen("TicketScreen");
}
}
get isTicketScreenShown() {
return this.pos.mainScreen.component === TicketScreen;
}
get orderCount() {
// FIXME POSREF: can this condition ever be false?
if (this.env.pos) {
return this.env.pos.get_order_list().length;
}
return 0;
}
}
@@ -6,8 +6,16 @@
<div t-if="pos.tempScreen" class="block-top-header" />
<div class="pos-branding">
<img t-if="!env.isMobile" class="pos-logo" t-on-click="() => debug.toggleWidget()" src="/point_of_sale/static/src/img/logo.png" alt="Logo" />
<CashMoveButton t-if="props.showCashMoveButton" />
<TicketButton />
<div t-if="props.showCashMoveButton" class="cash-move-button" t-on-click="onCashMoveButtonClick">
<i class="fa fa-money" aria-hidden="true"></i>
<span style="padding-left: 10px;">Cash In/Out</span>
</div>
<div class="ticket-button" t-att-class="{ highlight: isTicketScreenShown }" t-on-click="onTicketButtonClick">
<div class="with-badge" t-att-badge="orderCount">
<i class="fa fa-ticket" aria-hidden="true"></i>
</div>
<div t-if="!env.isMobile">Orders</div>
</div>
</div>
<div class="pos-rightheader">
<div class="status-buttons">
@@ -2,12 +2,12 @@
import { reactive } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { usePos } from "@point_of_sale/app/pos_hook";
export class PopupContainer extends PosComponent {
export class PopupContainer extends LegacyComponent {
static template = "point_of_sale.PopupContainer";
setup() {
// FIXME POSREF: remove this after PosComponent is removed.
// FIXME POSREF: remove this after LegacyComponent is removed.
this.__owl__.childEnv = usePos().legacyEnv;
}
}
+4 -23
View File
@@ -3,7 +3,7 @@
import { loadCSS } from "@web/core/assets";
import { useListener, useBus, useService } from "@web/core/utils/hooks";
import BarcodeParser from "barcodes.BarcodeParser";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { batched } from "@point_of_sale/js/utils";
import { debounce } from "@web/core/utils/timing";
import { Transition } from "@web/core/transition";
@@ -13,7 +13,6 @@ import { Navbar } from "@point_of_sale/app/navbar/navbar";
// ChromeAdapter imports
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { configureGui } from "@point_of_sale/js/Gui";
import { registry } from "@web/core/registry";
import { pos_env as env } from "@point_of_sale/js/pos_env";
@@ -34,8 +33,9 @@ import { usePos } from "@point_of_sale/app/pos_hook";
/**
* Chrome is the root component of the PoS App.
*/
export class Chrome extends PosComponent {
export class Chrome extends LegacyComponent {
static template = "Chrome"; // FIXME POSREF namespace templates
static components = { Transition, MainComponentsContainer, WithEnv, ErrorHandler, Navbar };
setup() {
this.pos = usePos();
this.popup = useService("popup");
@@ -65,6 +65,7 @@ export class Chrome extends PosComponent {
"pos_notification",
"number_buffer",
"popup",
"sale_order_fetcher",
]) {
env.services[service] = this.wowlEnv.services[service];
}
@@ -91,7 +92,6 @@ export class Chrome extends PosComponent {
useExternalListener(window, "beforeunload", this._onBeforeUnload);
useListener("close-pos", this._closePos);
useListener("loading-skip-callback", () => this.env.proxy.stop_searching());
useListener("set-sync-status", this._onSetSyncStatus);
useListener("connect-to-proxy", this.connect_to_proxy);
useBus(this.env.posbus, "start-cash-control", this.openCashControl);
useService("number_buffer").activate();
@@ -152,7 +152,6 @@ export class Chrome extends PosComponent {
// FIXME POSREF: use a silent RPC instead
const BlockUiFromRegistry = registry.category("main_components").get("BlockUI");
registry.category("main_components").remove("BlockUI");
configureGui({ component: this }); // FIXME POSREF: move Gui functions to services
try {
await this.env.pos.load_server_data();
@@ -350,10 +349,6 @@ export class Chrome extends PosComponent {
}
}
}
_onSetSyncStatus({ detail: { status, pending } }) {
this.env.pos.synch.status = status;
this.env.pos.synch.pending = pending;
}
/**
* Save `env.pos.toRefundLines` in localStorage on beforeunload - closing the
* browser, reloading or going to other page.
@@ -443,17 +438,3 @@ export class Chrome extends PosComponent {
Promise.reject(err);
}
}
Object.defineProperty(Chrome, "components", {
get() {
return Object.assign(
{
Transition,
MainComponentsContainer,
WithEnv,
ErrorHandler,
Navbar,
},
PosComponent.components
);
},
});
@@ -1,67 +0,0 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { _lt } from "web.core";
import { renderToString } from "@web/core/utils/render";
import { CashMovePopup } from "@point_of_sale/js/Popups/CashMovePopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { useService } from "@web/core/utils/hooks";
const TRANSLATED_CASH_MOVE_TYPE = {
in: _lt("in"),
out: _lt("out"),
};
export class CashMoveButton extends PosComponent {
static template = "point_of_sale.CashMoveButton";
setup() {
super.setup(...arguments);
this.popup = useService("popup");
this.notification = useService("pos_notification");
}
async onClick() {
const { confirmed, payload } = await this.popup.add(CashMovePopup);
if (!confirmed) {
return;
}
const { type, amount, reason } = payload;
const translatedType = TRANSLATED_CASH_MOVE_TYPE[type];
const formattedAmount = this.env.pos.format_currency(amount);
if (!amount) {
return this.notification.add(
_.str.sprintf(this.env._t("Cash in/out of %s is ignored."), formattedAmount),
3000
);
}
const extras = { formattedAmount, translatedType };
await this.rpc({
model: "pos.session",
method: "try_cash_in_out",
args: [[this.env.pos.pos_session.id], type, amount, reason, extras],
});
if (this.env.proxy.printer) {
const renderedReceipt = renderToString("point_of_sale.CashMoveReceipt", {
_receipt: this._getReceiptInfo({ ...payload, translatedType, formattedAmount }),
});
const printResult = await this.env.proxy.printer.print_receipt(renderedReceipt);
if (!printResult.successful) {
this.popup.add(ErrorPopup, {
title: printResult.message.title,
body: printResult.message.body,
});
}
}
this.notification.add(
_.str.sprintf(this.env._t("Successfully made a cash %s of %s."), type, formattedAmount),
3000
);
}
_getReceiptInfo(payload) {
const result = { ...payload };
result.cashier = this.env.pos.get_cashier();
result.company = this.env.pos.company;
return result;
}
}
@@ -1,9 +1,9 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
// Previously UsernameWidget
export class CashierName extends PosComponent {
export class CashierName extends LegacyComponent {
static template = "CashierName";
get username() {
@@ -1,10 +1,10 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { useState } = owl;
export class CustomerFacingDisplayButton extends PosComponent {
export class CustomerFacingDisplayButton extends LegacyComponent {
static template = "CustomerFacingDisplayButton";
setup() {
@@ -1,12 +1,12 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useService } from "@web/core/utils/hooks";
import { ClosePosPopup } from "@point_of_sale/js/Popups/ClosePosPopup";
// Previously HeaderButtonWidget
// This is the close session button
export class HeaderButton extends PosComponent {
export class HeaderButton extends LegacyComponent {
static template = "HeaderButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { onMounted, onWillUnmount, useState } = owl;
// Previously ProxyStatusWidget
export class ProxyStatus extends PosComponent {
export class ProxyStatus extends LegacyComponent {
static template = "ProxyStatus";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useService } from "@web/core/utils/hooks";
import { renderToString } from "@web/core/utils/render";
import { ErrorPopup } from "../Popups/ErrorPopup";
export class SaleDetailsButton extends PosComponent {
export class SaleDetailsButton extends LegacyComponent {
static template = "SaleDetailsButton";
setup() {
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class SyncNotification extends PosComponent {
export class SyncNotification extends LegacyComponent {
static template = "SyncNotification";
onClick() {
@@ -1,30 +0,0 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { TicketScreen } from "@point_of_sale/js/Screens/TicketScreen/TicketScreen";
export class TicketButton extends PosComponent {
static template = "TicketButton";
setup() {
this.pos = usePos();
}
onClick() {
if (this.isTicketScreenShown) {
this.env.posbus.trigger("ticket-button-clicked");
} else {
this.pos.showScreen("TicketScreen");
}
}
get isTicketScreenShown() {
return this.pos.mainScreen.component === TicketScreen;
}
get count() {
if (this.env.pos) {
return this.env.pos.get_order_list().length;
} else {
return 0;
}
}
}
-29
View File
@@ -1,29 +0,0 @@
/** @odoo-module */
const { status } = owl;
const config = {};
/**
* Call this when the user interface is ready. Provide the component
* that will be used to control the ui.
* @param {component} component component having the ui methods.
*/
export const configureGui = ({ component }) => {
config.component = component;
config.availableMethods = new Set(["setSyncStatus"]);
};
export class GuiNotReadyError extends Error {}
// FIXME POSREF: remove this entirely.
export const Gui = new Proxy(config, {
get(target, key) {
const { component, availableMethods } = target;
if (!component) {
throw new Error(`Call 'configureGui' before using Gui.`);
}
const isMounted = status(component) === "mounted";
if (availableMethods.has(key) && isMounted) {
return component[key].bind(component);
}
throw new GuiNotReadyError(`Attempted get ${key} on Gui when Chrome is not yet mounted.`);
},
});
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useService } from "@web/core/utils/hooks";
import { ConfirmPopup } from "../Popups/ConfirmPopup";
import { ErrorPopup } from "../Popups/ErrorPopup";
@@ -13,7 +13,7 @@ const { useRef } = owl;
* `order-receipt` in the template of the Component that extends
* this abstract component.
*/
export class AbstractReceiptScreen extends PosComponent {
export class AbstractReceiptScreen extends LegacyComponent {
setup() {
super.setup();
this.orderReceipt = useRef("order-receipt");
@@ -1,7 +1,7 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class CurrencyAmount extends PosComponent {
export class CurrencyAmount extends LegacyComponent {
static template = "CurrencyAmount";
}
@@ -1,7 +1,7 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { onMounted, useExternalListener } = owl;
@@ -27,7 +27,7 @@ const { onMounted, useExternalListener } = owl;
*
* @trigger 'drag-end' when dragging ended with payload `{ loc: { top, left } }`
*/
export class Draggable extends PosComponent {
export class Draggable extends LegacyComponent {
static template = "Draggable";
setup() {
@@ -1,17 +1,15 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class IndependentToOrderScreen extends PosComponent {
export class IndependentToOrderScreen extends LegacyComponent {
static storeOnOrder = false;
setup() {
super.setup(...arguments);
this.pos = usePos();
}
close() {
const order = this.env.pos.get_order();
const { name: screenName } = order.get_screen_data();
this.pos.showScreen(screenName);
this.pos.closeScreen();
}
}
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class MobileOrderWidget extends PosComponent {
export class MobileOrderWidget extends LegacyComponent {
static template = "MobileOrderWidget";
get order() {
@@ -1,7 +1,7 @@
/** @odoo-module */
import { useAutofocus, useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { useExternalListener, useState } = owl;
@@ -28,7 +28,7 @@ const { useExternalListener, useState } = owl;
* NOTE: The payload of the emitted event is accessible via the `detail`
* field of the event.
*/
export class SearchBar extends PosComponent {
export class SearchBar extends LegacyComponent {
static template = "point_of_sale.SearchBar";
setup() {
@@ -1,7 +1,7 @@
/** @odoo-module */
import { useExternalListener } from "@odoo/owl";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
/**
* Implement this abstract class by extending it like so:
@@ -28,7 +28,7 @@ import { PosComponent } from "@point_of_sale/js/PosComponent";
* // otherwise, payload = null
* ```
*/
export class AbstractAwaitablePopup extends PosComponent {
export class AbstractAwaitablePopup extends LegacyComponent {
setup() {
super.setup(...arguments);
useExternalListener(window, "keyup", this._onWindowKeyup);
@@ -1,52 +0,0 @@
/** @odoo-module */
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { parse } from "web.field_utils";
const { useRef, useState, onMounted } = owl;
export class CashMovePopup extends AbstractAwaitablePopup {
static template = "point_of_sale.CashMovePopup";
setup() {
super.setup();
this.state = useState({
inputType: "out", // '' | 'in' | 'out'
inputAmount: "",
inputReason: "",
errorMessage: "",
});
this.inputAmountRef = useRef("input-amount-ref");
onMounted(() => this.inputAmountRef.el.focus());
}
confirm() {
try {
parse.float(this.state.inputAmount);
} catch {
this.state.errorMessage = this.env._t("Invalid amount");
return;
}
if (this.state.inputAmount < 0) {
this.state.errorMessage = this.env._t("Insert a positive amount");
return;
}
return super.confirm();
}
_onAmountKeypress(event) {
if (["-", "+"].includes(event.key)) {
event.preventDefault();
}
}
onClickButton(type) {
this.state.inputType = type;
this.state.errorMessage = "";
this.inputAmountRef.el.focus();
}
getPayload() {
return {
amount: parse.float(this.state.inputAmount),
reason: this.state.inputReason.trim(),
type: this.state.inputType,
};
}
}
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
/**
* props {
@@ -9,7 +9,7 @@ import { PosComponent } from "@point_of_sale/js/PosComponent";
* item: object,
* }
*/
export class EditListInput extends PosComponent {
export class EditListInput extends LegacyComponent {
static template = "EditListInput";
onKeyup(event) {
@@ -1,10 +1,10 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
const { useState, useSubEnv } = owl;
export class BaseProductAttribute extends PosComponent {
export class BaseProductAttribute extends LegacyComponent {
setup() {
super.setup();
this.env.attribute_components.push(this);
@@ -62,7 +62,7 @@ export class ProductConfiguratorPopup extends AbstractAwaitablePopup {
static components = {
RadioProductAttribute,
SelectProductAttribute,
ColorProductAttribute
ColorProductAttribute,
};
setup() {
@@ -1,15 +0,0 @@
/** @odoo-module */
import { LegacyComponent } from "@web/legacy/legacy_component";
export class PosComponent extends LegacyComponent {
static components = {};
/**
* Control the SyncNotification component.
* @param {String} status 'connected' | 'connecting' | 'disconnected' | 'error'
* @param {String} pending number of pending orders to sync
*/
setSyncStatus(status, pending) {
this.trigger("set-sync-status", { status, pending });
}
}
@@ -2,13 +2,13 @@
import { _t } from "web.core";
import { getDataURLFromFile } from "web.utils";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { useService } from "@web/core/utils/hooks";
const { onMounted, onWillUnmount } = owl;
export class PartnerDetailsEdit extends PosComponent {
export class PartnerDetailsEdit extends LegacyComponent {
static template = "PartnerDetailsEdit";
setup() {
@@ -19,7 +19,7 @@ export class PartnerDetailsEdit extends PosComponent {
this.changes = {
country_id: partner.country_id && partner.country_id[0],
state_id: partner.state_id && partner.state_id[0],
property_product_pricelist: this.setDefaultPricelist(partner)
property_product_pricelist: this.setDefaultPricelist(partner),
};
onMounted(() => {
@@ -32,9 +32,8 @@ export class PartnerDetailsEdit extends PosComponent {
}
setDefaultPricelist(partner) {
if (partner.property_product_pricelist) {
return partner.property_product_pricelist[0]
}
else if (this.env.pos.default_pricelist) {
return partner.property_product_pricelist[0];
} else if (this.env.pos.default_pricelist) {
return this.env.pos.default_pricelist.id;
}
return false;
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class PartnerLine extends PosComponent {
export class PartnerLine extends LegacyComponent {
static template = "PartnerLine";
get highlight() {
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { registry } from "@web/core/registry";
import { debounce } from "@web/core/utils/timing";
@@ -27,7 +27,7 @@ const { onWillUnmount, useRef } = owl;
*
* @props partner - originally selected partner
*/
export class PartnerListScreen extends PosComponent {
export class PartnerListScreen extends LegacyComponent {
static components = { PartnerDetailsEdit, PartnerLine };
static template = "PartnerListScreen";
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class PSNumpadInputButton extends PosComponent {
export class PSNumpadInputButton extends LegacyComponent {
static template = "PSNumpadInputButton";
get _class() {
@@ -1,7 +1,7 @@
/** @odoo-module */
import { parse } from "web.field_utils";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useErrorHandlers } from "@point_of_sale/js/custom_hooks";
import { registry } from "@web/core/registry";
import { useListener, useService } from "@web/core/utils/hooks";
@@ -17,7 +17,7 @@ import { PaymentScreenPaymentLines } from "./PaymentScreenPaymentLines";
import { PaymentScreenStatus } from "./PaymentScreenStatus";
import { usePos } from "@point_of_sale/app/pos_hook";
export class PaymentScreen extends PosComponent {
export class PaymentScreen extends LegacyComponent {
static template = "PaymentScreen";
static components = {
PaymentScreenNumpad,
@@ -1,10 +1,10 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { PSNumpadInputButton } from "./PSNumpadInputButton";
export class PaymentScreenNumpad extends PosComponent {
export class PaymentScreenNumpad extends LegacyComponent {
static components = { PSNumpadInputButton };
static template = "PaymentScreenNumpad";
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class PaymentScreenPaymentLines extends PosComponent {
export class PaymentScreenPaymentLines extends LegacyComponent {
static template = "PaymentScreenPaymentLines";
formatLineAmount(paymentline) {
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class PaymentScreenStatus extends PosComponent {
export class PaymentScreenStatus extends LegacyComponent {
static template = "PaymentScreenStatus";
get changeText() {
@@ -1,13 +1,13 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
/**
* @props partner
* @emits click-partner
* @emits click-pay
*/
export class ActionpadWidget extends PosComponent {
export class ActionpadWidget extends LegacyComponent {
static template = "ActionpadWidget";
static defaultProps = {
isActionButtonHighlighted: false,
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class CategoryButton extends PosComponent {
export class CategoryButton extends LegacyComponent {
static template = "CategoryButton";
get imageUrl() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { TextAreaPopup } from "@point_of_sale/js/Popups/TextAreaPopup";
export class OrderlineCustomerNoteButton extends PosComponent {
export class OrderlineCustomerNoteButton extends LegacyComponent {
static template = "OrderlineCustomerNoteButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { ProductInfoPopup } from "@point_of_sale/js/Popups/ProductInfoPopup";
export class ProductInfoButton extends PosComponent {
export class ProductInfoButton extends LegacyComponent {
static template = "ProductInfoButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener } from "@web/core/utils/hooks";
export class RefundButton extends PosComponent {
export class RefundButton extends LegacyComponent {
static template = "point_of_sale.RefundButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { SelectionPopup } from "@point_of_sale/js/Popups/SelectionPopup";
export class SetFiscalPositionButton extends PosComponent {
export class SetFiscalPositionButton extends LegacyComponent {
static template = "SetFiscalPositionButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { SelectionPopup } from "@point_of_sale/js/Popups/SelectionPopup";
export class SetPricelistButton extends PosComponent {
export class SetPricelistButton extends LegacyComponent {
static template = "SetPricelistButton";
setup() {
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
/**
* @prop {'quantity' | 'price' | 'discount'} activeMode
@@ -9,7 +9,7 @@ import { PosComponent } from "@point_of_sale/js/PosComponent";
* @event set-numpad-mode - triggered when mode button is clicked
* @event numpad-click-input - triggered when numpad button is clicked
*/
export class NumpadWidget extends PosComponent {
export class NumpadWidget extends LegacyComponent {
static template = "NumpadWidget";
static defaultProps = {
disabledModes: [],
@@ -1,9 +1,9 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { float_is_zero } from "web.utils";
export class OrderSummary extends PosComponent {
export class OrderSummary extends LegacyComponent {
static template = "OrderSummary";
getTotal() {
@@ -1,7 +1,7 @@
/** @odoo-module */
import { useListener, useService } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { EditListPopup } from "@point_of_sale/js/Popups/EditListPopup";
import { Orderline } from "./Orderline";
@@ -9,7 +9,7 @@ import { OrderSummary } from "./OrderSummary";
const { useEffect, useRef } = owl;
export class OrderWidget extends PosComponent {
export class OrderWidget extends LegacyComponent {
static components = { Orderline, OrderSummary };
static template = "OrderWidget";
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class Orderline extends PosComponent {
export class Orderline extends LegacyComponent {
static template = "Orderline";
selectLine() {
@@ -1,8 +1,8 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class ProductItem extends PosComponent {
export class ProductItem extends LegacyComponent {
static template = "ProductItem";
/**
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ControlButtonsMixin } from "@point_of_sale/js/ControlButtonsMixin";
import { registry } from "@web/core/registry";
import { useListener, useService } from "@web/core/utils/hooks";
@@ -24,7 +24,7 @@ import { usePos } from "@point_of_sale/app/pos_hook";
const { onMounted, useState } = owl;
export class ProductScreen extends ControlButtonsMixin(PosComponent) {
export class ProductScreen extends ControlButtonsMixin(LegacyComponent) {
static template = "ProductScreen";
static components = {
ActionpadWidget,
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useListener } from "@web/core/utils/hooks";
import { usePos } from "@point_of_sale/app/pos_hook";
@@ -9,7 +9,7 @@ import { ProductsWidgetControlPanel } from "./ProductsWidgetControlPanel";
const { useState } = owl;
export class ProductsWidget extends PosComponent {
export class ProductsWidget extends LegacyComponent {
static components = { ProductItem, ProductsWidgetControlPanel };
static template = "ProductsWidget";
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { debounce } from "@web/core/utils/timing";
import { usePos } from "@point_of_sale/app/pos_hook";
@@ -9,7 +9,7 @@ import { CategoryButton } from "./CategoryButton";
import { onMounted, onWillUnmount, useState } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
export class ProductsWidgetControlPanel extends PosComponent {
export class ProductsWidgetControlPanel extends LegacyComponent {
static components = { CategoryButton };
static template = "ProductsWidgetControlPanel";
@@ -1,12 +1,12 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { WrappedProductNameLines } from "./WrappedProductNameLines";
const { onWillUpdateProps } = owl;
export class OrderReceipt extends PosComponent {
export class OrderReceipt extends LegacyComponent {
static components = { WrappedProductNameLines };
static template = "OrderReceipt";
@@ -34,7 +34,7 @@ export class OrderReceipt extends PosComponent {
return this._receiptEnv;
}
get shippingDate() {
return this.receiptEnv.shippingDate
return this.receiptEnv.shippingDate;
}
isSimple(line) {
return (
@@ -20,9 +20,9 @@ export class ReceiptScreen extends AbstractReceiptScreen {
this.pos = usePos();
useErrorHandlers();
this.orderReceipt = useRef("order-receipt");
const order = this.currentOrder;
const partner = order.get_partner();
this.orderUiState = order.uiState.ReceiptScreen;
this.currentOrder = this.env.pos.get_order();
const partner = this.currentOrder.get_partner();
this.orderUiState = this.currentOrder.uiState.ReceiptScreen;
this.orderUiState.inputEmail =
this.orderUiState.inputEmail || (partner && partner.email) || "";
this.is_email = is_email;
@@ -78,9 +78,6 @@ export class ReceiptScreen extends AbstractReceiptScreen {
const tipAmountStr = this.env.pos.format_currency(tipAmount);
return `${orderAmountStr} + ${tipAmountStr} tip`;
}
get currentOrder() {
return this.env.pos.get_order();
}
get nextScreen() {
return { name: "ProductScreen" };
}
@@ -1,7 +1,7 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class WrappedProductNameLines extends PosComponent {
export class WrappedProductNameLines extends LegacyComponent {
static template = "WrappedProductNameLines";
}
@@ -1,13 +1,13 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { round_precision as round_pr } from "web.utils";
import { registry } from "@web/core/registry";
import { usePos } from "@point_of_sale/app/pos_hook";
const { onMounted, onWillUnmount, useExternalListener, useState } = owl;
export class ScaleScreen extends PosComponent {
export class ScaleScreen extends LegacyComponent {
static template = "ScaleScreen";
/**
@@ -1,12 +1,12 @@
/** @odoo-module */
import { useListener, useService } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { ConfirmPopup } from "@point_of_sale/js/Popups/ConfirmPopup";
import { usePos } from "@point_of_sale/app/pos_hook";
export class InvoiceButton extends PosComponent {
export class InvoiceButton extends LegacyComponent {
static template = "InvoiceButton";
setup() {
@@ -1,10 +1,10 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { usePos } from "@point_of_sale/app/pos_hook";
export class ReprintReceiptButton extends PosComponent {
export class ReprintReceiptButton extends LegacyComponent {
static template = "ReprintReceiptButton";
setup() {
@@ -1,12 +1,12 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { OrderlineDetails } from "./OrderlineDetails";
/**
* @props {models.Order} order
*/
export class OrderDetails extends PosComponent {
export class OrderDetails extends LegacyComponent {
static components = { OrderlineDetails };
static template = "OrderDetails";
@@ -1,13 +1,13 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { format } from "web.field_utils";
import { round_precision as round_pr } from "web.utils";
/**
* @props {pos.order.line} line
*/
export class OrderlineDetails extends PosComponent {
export class OrderlineDetails extends LegacyComponent {
static template = "OrderlineDetails";
get line() {
@@ -16,8 +16,7 @@ import { OrderDetails } from "../TicketScreen/OrderDetails";
import { ReprintReceiptButton } from "./ControlButtons/ReprintReceiptButton";
import { SearchBar } from "../../Misc/SearchBar";
import { usePos } from "@point_of_sale/app/pos_hook";
const { onMounted, onWillUnmount, useState } = owl;
import { onWillUnmount, onMounted, useState } from "@odoo/owl";
export class TicketScreen extends IndependentToOrderScreen {
static template = "TicketScreen";
@@ -43,7 +42,6 @@ export class TicketScreen extends IndependentToOrderScreen {
super.setup();
this.pos = usePos();
this.popup = useService("popup");
useListener("close-screen", this._onCloseScreen);
useListener("filter-selected", this._onFilterSelected);
useListener("search", this._onSearch);
useListener("click-order", this._onClickOrder);
@@ -75,24 +73,18 @@ export class TicketScreen extends IndependentToOrderScreen {
};
Object.assign(this._state.ui, defaultUIState, this.props.ui || {});
onMounted(this.onMounted);
onWillUnmount(this.onWillUnmount);
}
//#region LIFECYCLE METHODS
onMounted() {
this.env.posbus.on("ticket-button-clicked", this, this.close);
setTimeout(() => {
// Show updated list of synced orders when going back to the screen.
onMounted(() => {
this._onFilterSelected({ detail: { filter: this._state.ui.filter } });
});
}
onWillUnmount() {
this.env.posbus.off("ticket-button-clicked", this);
}
//#endregion
//#region EVENT HANDLERS
_onCloseScreen() {
this.close();
onWillUnmount(() => {
/**
* Automatically create new order when there is no currently active order.
* Important in fiscal modules to keep the sequence of the orders.
*/
if (this.env.pos.orders.length == 0 && this.allowNewOrders) {
this.env.pos.add_new_order();
}
});
}
async _onFilterSelected(event) {
this._state.ui.filter = event.detail.filter;
@@ -286,19 +278,7 @@ export class TicketScreen extends IndependentToOrderScreen {
this.env.pos.set_order(destinationOrder);
}
this._onCloseScreen();
}
//#endregion
//#region PUBLIC METHODS
close() {
/**
* Automatically create new order when there is no currently active order.
* Important in fiscal modules to keep the sequence of the orders.
*/
if (this.env.pos.orders.length == 0) {
this.env.pos.add_new_order();
}
super.close();
this.close();
}
getSelectedSyncedOrder() {
if (this._state.ui.filter == "SYNCED") {
@@ -311,9 +291,12 @@ export class TicketScreen extends IndependentToOrderScreen {
return this._state.ui.selectedOrderlineIds[this._state.ui.selectedSyncedOrderId];
}
/**
* Override to conditionally show the new ticket button.
* Override to conditionally show the new order button, or prevent order
* creation when leaving the screen.
*
* @returns {boolean}
*/
shouldShowNewOrderButton() {
get allowNewOrders() {
return true;
}
getFilteredOrderList() {
@@ -3686,101 +3686,6 @@ td {
}
}
/** CashMovePopup **/
.cash-move-popup {
top: 20% !important;
}
.cash-move {
display: flex;
flex-flow: column;
}
.cash-move .input-amount {
display: flex;
flex-flow: row;
}
.cash-move .input-amount .input-type {
height: 40px;
line-height:40px;
text-align:center;
border-radius: 2px;
padding: 0 12px;
margin-right: 10px;
font-size: 14px;
font-weight: bold;
cursor: pointer;
border: solid 1px rgba(60,60,60,0.1);
background: rgba(0,0,0,0.05);
white-space: nowrap;
}
.cash-move .input-amount .input-type.highlight {
background: $primary !important;
border: solid 1px #64AF8A !important;
color: white !important;
}
.cash-move .input-amount .red-highlight {
background: #bd2222 !important;
border: solid 1px #bd2222 !important;
color: white !important;
}
.cash-move .input-amount input {
width: 100%;
min-height: auto;
text-align: right;
padding-right: 30px;
}
.cash-move .input-amount .input-field {
position: relative;
flex-grow: 1;
}
.cash-move .input-amount .input-field span.currency {
position: absolute;
right: 10px;
top: 10px;
}
.cash-move .input-amount .input-field span.left-currency {
position: absolute;
left: 10px;
top: 10px;
background-color: #fff;
padding-right: 8px;
}
.cash-move textarea {
resize: none;
margin-top: 10px;
margin-bottom: 10px;
}
.cash-move .error-message {
color: rgb(197, 52, 0);
text-align: left;
padding-left: 5px;
}
.pos .popup footer.cash-move {
display: block;
width: calc(100% - 36px);
padding: 10px 18px 10px 18px;
}
.pos .popup .footer.cash-move .button.confirm {
float: left;
}
.pos .popup .footer.cash-move .button.cancel {
margin-right: 0;
}
/* For LoadingScreen */
.lds-ellipsis {
@@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="point_of_sale.CashMoveButton" owl="1">
<div class="cash-move-button" t-on-click="onClick">
<i class="fa fa-money" aria-hidden="true"></i>
<span style="padding-left: 10px;">Cash In/Out</span>
</div>
</t>
</templates>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates id="template" xml:space="preserve">
<t t-name="TicketButton" owl="1">
<div class="ticket-button" t-att-class="{ highlight: isTicketScreenShown }" t-on-click="onClick">
<div class="with-badge" t-att-badge="count">
<i class="fa fa-ticket" aria-hidden="true"></i>
</div>
<div t-if="!env.isMobile">Orders</div>
</div>
</t>
</templates>
@@ -8,7 +8,7 @@
<div class="controls">
<t t-if="!env.isMobile || !state.showSearchBar">
<div class="buttons">
<button class="discard" t-on-click="() => this.trigger('close-screen')">
<button class="discard" t-on-click="() => this.pos.closeScreen()">
<span class="search-icon">
<i class="fa fa-angle-double-left"/>
</span>
@@ -16,7 +16,7 @@
Back
</t>
</button>
<button t-if="shouldShowNewOrderButton()" class="highlight" t-on-click="() => this.trigger('create-new-order')">New Order</button>
<button t-if="allowNewOrders" class="highlight" t-on-click="() => this.trigger('create-new-order')">New Order</button>
</div>
</t>
<t t-if="env.isMobile">
@@ -1,7 +1,7 @@
/** @odoo-module */
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import makeTestEnvironment from "web.test_env";
import { click, getFixture, mount, nextTick, triggerEvent } from "@web/../tests/helpers/utils";
import { clearRegistryWithCleanup, makeTestEnv } from "@web/../tests/helpers/mock_env";
@@ -38,7 +38,7 @@ CustomPopup2.template = xml/* html */ `
</div>
`;
class Root extends PosComponent {
class Root extends LegacyComponent {
static components = { MainComponentsContainer };
setup() {
super.setup();
@@ -1,12 +1,12 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
export class DiscountButton extends PosComponent {
export class DiscountButton extends LegacyComponent {
static template = "DiscountButton";
setup() {
+3 -5
View File
@@ -2,14 +2,12 @@
import { CashierName } from "@point_of_sale/js/ChromeWidgets/CashierName";
import { patch } from "@web/core/utils/patch";
import { SelectCashierMixin } from "@pos_hr/js/SelectCashierMixin";
import { useBarcodeReader } from "@point_of_sale/js/custom_hooks";
import { useCashierSelector } from "@pos_hr/js/SelectCashierMixin";
patch(CashierName.prototype, "pos_hr.CashierName SelectCashierMixin", SelectCashierMixin);
patch(CashierName.prototype, "pos_hr.CashierName methods", {
patch(CashierName.prototype, "pos_hr.CashierName", {
setup() {
this._super(...arguments);
useBarcodeReader({ cashier: this.barcodeCashierAction });
this.selectCashier = useCashierSelector();
},
//@Override
get avatar() {
+1 -1
View File
@@ -7,7 +7,7 @@ patch(Chrome.prototype, "pos_hr.Chrome", {
async start() {
await this._super(...arguments);
if (this.env.pos.config.module_pos_hr) {
this.pos.showTempScreen("LoginScreen");
this.pos.showTempScreen("LoginScreen"); // FIXME POSREF: use startScreen instead.
}
},
get showCashMoveButton() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { useState } = owl;
export class HeaderLockButton extends PosComponent {
export class HeaderLockButton extends LegacyComponent {
static template = "HeaderLockButton";
setup() {
+13 -29
View File
@@ -1,46 +1,30 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { SelectCashierMixin } from "@pos_hr/js/SelectCashierMixin";
import { useBarcodeReader } from "@point_of_sale/js/custom_hooks";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useCashierSelector } from "@pos_hr/js/SelectCashierMixin";
import { registry } from "@web/core/registry";
import { patch } from "@web/core/utils/patch";
import { usePos } from "@point_of_sale/app/pos_hook";
export class LoginScreen extends PosComponent {
export class LoginScreen extends LegacyComponent {
static template = "LoginScreen";
}
// FIXME POSREF stop this double patch once the mixin is converted to a hook.
patch(LoginScreen.prototype, "pos_hr.LoginScreen SelectCashierMixin", SelectCashierMixin);
patch(LoginScreen.prototype, "pos_hr.LoginScreen methods", {
setup() {
this._super(...arguments);
useBarcodeReader({ cashier: this.barcodeCashierAction }, true);
super.setup(...arguments);
this.selectCashier = useCashierSelector({
onCashierChanged: () => this.back(),
});
this.pos = usePos();
},
async selectCashier() {
if (await this._super(...arguments)) {
this.back();
}
},
async barcodeCashierAction(code) {
if ((await this._super(code)) && this.env.pos.get_cashier().id) {
this.back();
}
},
}
back() {
this.props.resolve({ confirmed: false, payload: false });
this.pos.closeTempScreen();
this.env.pos.hasLoggedIn = true;
this.env.posbus.trigger("start-cash-control");
},
confirm() {
this.props.resolve({ confirmed: true, payload: true });
this.pos.closeTempScreen();
},
}
get shopName() {
return this.env.pos.config.name;
},
});
}
}
registry.category("pos_screens").add("LoginScreen", LoginScreen);
@@ -1,45 +1,66 @@
/** @odoo-module */
/* global Sha1 */
import { _t } from "@web/core/l10n/translation";
import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
import { SelectionPopup } from "@point_of_sale/js/Popups/SelectionPopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { useService } from "@web/core/utils/hooks";
import { useEnv } from "@odoo/owl";
import { useBarcodeReader } from "@point_of_sale/js/custom_hooks";
// FIXME POSREF make this into a hook or something
export const SelectCashierMixin = {
setup() {
this._super(...arguments);
this.popup = useService("popup");
},
async askPin(employee) {
const { confirmed, payload: inputPin } = await this.popup.add(NumberPopup, {
export function useCashierSelector({ onCashierChanged } = { onCashierChanged: () => {} }) {
const popup = useService("popup");
const env = useEnv();
useBarcodeReader(
{
async cashier(code) {
const employee = env.pos.employees.find(
(emp) => emp.barcode === Sha1.hash(code.code)
);
if (
employee &&
employee !== env.pos.get_cashier() &&
(!employee.pin || (await checkPin(employee)))
) {
env.pos.set_cashier(employee);
if (onCashierChanged) {
onCashierChanged();
}
}
return employee;
},
},
true
);
async function checkPin(employee) {
const { confirmed, payload: inputPin } = await popup.add(NumberPopup, {
isPassword: true,
title: this.env._t("Password ?"),
startingValue: null,
title: _t("Password ?"),
});
if (!confirmed) {
return;
return false;
}
if (employee.pin === Sha1.hash(inputPin)) {
return employee;
} else {
await this.popup.add(ErrorPopup, {
title: this.env._t("Incorrect Password"),
if (employee.pin !== Sha1.hash(inputPin)) {
await popup.add(ErrorPopup, {
title: _t("Incorrect Password"),
});
return;
return false;
}
},
return true;
}
/**
* Select a cashier, the returning value will either be an object or nothing (undefined)
*/
async selectCashier() {
if (this.env.pos.config.module_pos_hr) {
const employeesList = this.env.pos.employees
.filter((employee) => employee.id !== this.env.pos.get_cashier().id)
return async function selectCashier() {
if (env.pos.config.module_pos_hr) {
const employeesList = env.pos.employees
.filter((employee) => employee.id !== env.pos.get_cashier().id)
.map((employee) => {
return {
id: employee.id,
@@ -48,34 +69,19 @@ export const SelectCashierMixin = {
isSelected: false,
};
});
let { confirmed, payload: employee } = await this.popup.add(SelectionPopup, {
title: this.env._t("Change Cashier"),
const { confirmed, payload: employee } = await popup.add(SelectionPopup, {
title: _t("Change Cashier"),
list: employeesList,
});
if (!confirmed) {
if (!confirmed || !employee || (employee.pin && !(await checkPin(employee)))) {
return;
}
if (employee && employee.pin) {
employee = await this.askPin(employee);
env.pos.set_cashier(employee);
if (onCashierChanged) {
onCashierChanged();
}
if (employee) {
this.env.pos.set_cashier(employee);
}
return employee;
}
},
async barcodeCashierAction(code) {
const employee = this.env.pos.employees.find((emp) => emp.barcode === Sha1.hash(code.code));
if (
employee &&
employee !== this.env.pos.get_cashier() &&
(!employee.pin || (await this.askPin(employee)))
) {
this.env.pos.set_cashier(employee);
}
return employee;
},
};
};
}
@@ -1,11 +1,11 @@
/** @odoo-module **/
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { TextInputPopup } from "@point_of_sale/js/Popups/TextInputPopup";
export class PromoCodeButton extends PosComponent {
export class PromoCodeButton extends LegacyComponent {
static template = "PromoCodeButton";
setup() {
@@ -1,10 +1,10 @@
/** @odoo-module **/
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener } from "@web/core/utils/hooks";
export class ResetProgramsButton extends PosComponent {
export class ResetProgramsButton extends LegacyComponent {
static template = "ResetProgramsButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module **/
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { SelectionPopup } from "@point_of_sale/js/Popups/SelectionPopup";
export class RewardButton extends PosComponent {
export class RewardButton extends LegacyComponent {
static template = "RewardButton";
setup() {
@@ -1,12 +1,12 @@
/** @odoo-module **/
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { SelectionPopup } from "@point_of_sale/js/Popups/SelectionPopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { useService } from "@web/core/utils/hooks";
export class eWalletButton extends PosComponent {
export class eWalletButton extends LegacyComponent {
static template = "point_of_sale.eWalletButton";
setup() {
@@ -1,9 +1,9 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class BackToFloorButton extends PosComponent {
export class BackToFloorButton extends LegacyComponent {
static template = "BackToFloorButton";
setup() {
@@ -4,6 +4,36 @@ import { Navbar } from "@point_of_sale/app/navbar/navbar";
import { patch } from "@web/core/utils/patch";
import { BackToFloorButton } from "./BackToFloorButton";
patch(Navbar, "pos_restaurant.Navbar", {
components: { ...Navbar.components, BackToFloorButton },
patch(Navbar.components, "pos_restaurant.Navbar components", { BackToFloorButton });
patch(Navbar.prototype, "pos_restaurant.Navbar", {
async onTicketButtonClick() {
if (
this.env.pos.config.iface_floorplan &&
!this.isTicketScreenShown &&
!this.env.pos.table
) {
try {
this.env.pos.setLoadingOrderState(true);
await this.env.pos._syncAllOrdersFromServer();
} finally {
this.env.pos.setLoadingOrderState(false);
this.pos.showScreen("TicketScreen");
}
} else {
return this._super(...arguments);
}
},
/**
* If no table is set to pos, which means the current main screen
* is floor screen, then the order count should be based on all the orders.
*/
get orderCount() {
if (!this.env.pos || !this.env.pos.config) {
return 0;
}
if (this.env.pos.config.iface_floorplan && this.env.pos.table) {
return this.env.pos.getTableOrders(this.env.pos.table.id).length;
}
return this._super(...arguments);
},
});
@@ -68,10 +68,19 @@ patch(PosStore.prototype, "pos_restaurant.PosStore", {
this.mainScreen.component !== FloorScreen
);
},
showScreen() {
showScreen(screenName) {
if (screenName === "FloorScreen" && this.globalState.table) {
this.globalState.unsetTable();
}
this._super(...arguments);
this.setIdleTimer();
},
closeScreen() {
if (this.globalState.config.iface_floorplan && !this.globalState.get_order()) {
return this.showScreen("FloorScreen");
}
return this._super(...arguments);
},
/**
* @override
* FIXME POSREF this is now dead code, check if we still want this
@@ -1,38 +0,0 @@
/** @odoo-module */
import { TicketButton } from "@point_of_sale/js/ChromeWidgets/TicketButton";
import { patch } from "@web/core/utils/patch";
patch(TicketButton.prototype, "pos_restaurant.TicketButton", {
async onClick() {
if (
this.env.pos.config.iface_floorplan &&
!this.isTicketScreenShown &&
!this.env.pos.table
) {
try {
this.env.pos.setLoadingOrderState(true);
await this.env.pos._syncAllOrdersFromServer();
} finally {
this.env.pos.setLoadingOrderState(false);
this.pos.showScreen("TicketScreen");
}
} else {
this._super(...arguments);
}
},
/**
* If no table is set to pos, which means the current main screen
* is floor screen, then the order count should be based on all the orders.
*/
get count() {
if (!this.env.pos || !this.env.pos.config) {
return 0;
}
if (this.env.pos.config.iface_floorplan && this.env.pos.table) {
return this.env.pos.getTableOrders(this.env.pos.table.id).length;
} else {
return this._super(...arguments);
}
},
});
@@ -1,11 +1,11 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { onMounted, useExternalListener } = owl;
export class Resizeable extends PosComponent {
export class Resizeable extends LegacyComponent {
static template = "Resizeable";
setup() {
@@ -1,10 +1,10 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
const { useState } = owl;
export class EditBar extends PosComponent {
export class EditBar extends LegacyComponent {
static template = "EditBar";
setup() {
@@ -1,14 +1,14 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { Draggable } from "@point_of_sale/js/Misc/Draggable";
import { Resizeable } from "../../Resizeable";
const { onMounted, onPatched } = owl;
export class EditableTable extends PosComponent {
export class EditableTable extends LegacyComponent {
static template = "EditableTable";
static components = { Draggable, Resizeable };
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { debounce } from "@web/core/utils/timing";
import { registry } from "@web/core/registry";
@@ -16,7 +16,7 @@ import { useService } from "@web/core/utils/hooks";
const { onPatched, onMounted, onWillUnmount, useRef, useState } = owl;
export class FloorScreen extends PosComponent {
export class FloorScreen extends LegacyComponent {
static components = { EditableTable, EditBar, TableWidget };
static template = "FloorScreen";
static storeOnOrder = false;
@@ -47,9 +47,6 @@ export class FloorScreen extends PosComponent {
this.state.floorMapScrollTop = this.floorMapRef.el.getBoundingClientRect().top;
}
onMounted() {
if (this.env.pos.table) {
this.env.pos.unsetTable();
}
this.env.posbus.trigger("start-cash-control");
this.floorMapRef.el.style.background = this.state.floorBackground;
this.state.floorMapScrollTop = this.floorMapRef.el.getBoundingClientRect().top;
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
/**
* props: {
@@ -8,7 +8,7 @@ import { PosComponent } from "@point_of_sale/js/PosComponent";
* table: table object,
* }
*/
export class TableWidget extends PosComponent {
export class TableWidget extends LegacyComponent {
static template = "TableWidget";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { TextAreaPopup } from "@point_of_sale/js/Popups/TextAreaPopup";
export class OrderlineNoteButton extends PosComponent {
export class OrderlineNoteButton extends LegacyComponent {
static template = "OrderlineNoteButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener } from "@web/core/utils/hooks";
export class PrintBillButton extends PosComponent {
export class PrintBillButton extends LegacyComponent {
static template = "PrintBillButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener } from "@web/core/utils/hooks";
export class SplitBillButton extends PosComponent {
export class SplitBillButton extends LegacyComponent {
static template = "SplitBillButton";
setup() {
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { useService } from "@web/core/utils/hooks";
@@ -11,7 +11,7 @@ import { useService } from "@web/core/utils/hooks";
* Also, the current order changes when the selectedOrder in pos is changed.
* After setting new current order, we update the listeners.
*/
export class SubmitOrderButton extends PosComponent {
export class SubmitOrderButton extends LegacyComponent {
static template = "SubmitOrderButton";
setup() {
@@ -1,12 +1,12 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener, useService } from "@web/core/utils/hooks";
import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
export class TableGuestsButton extends PosComponent {
export class TableGuestsButton extends LegacyComponent {
static template = "TableGuestsButton";
setup() {
@@ -1,11 +1,11 @@
/** @odoo-module */
import { usePos } from "@point_of_sale/app/pos_hook";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { ProductScreen } from "@point_of_sale/js/Screens/ProductScreen/ProductScreen";
import { useListener } from "@web/core/utils/hooks";
export class TransferOrderButton extends PosComponent {
export class TransferOrderButton extends LegacyComponent {
static template = "TransferOrderButton";
setup() {
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { useListener } from "@web/core/utils/hooks";
import { Order } from "@point_of_sale/js/models";
@@ -10,7 +10,7 @@ import { usePos } from "@point_of_sale/app/pos_hook";
const { useState, onMounted } = owl;
export class SplitBillScreen extends PosComponent {
export class SplitBillScreen extends LegacyComponent {
static template = "SplitBillScreen";
static components = { SplitOrderline };
@@ -1,9 +1,9 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
export class SplitOrderline extends PosComponent {
export class SplitOrderline extends LegacyComponent {
static template = "SplitOrderline";
setup() {
@@ -1,5 +1,5 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { TicketScreen } from "@point_of_sale/js/Screens/TicketScreen/TicketScreen";
import { useAutofocus } from "@web/core/utils/hooks";
import { patch } from "@web/core/utils/patch";
@@ -9,19 +9,6 @@ import { ConfirmPopup } from "@point_of_sale/js/Popups/ConfirmPopup";
const { useState } = owl;
patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", {
close() {
if (!this.env.pos.config.iface_floorplan) {
this._super(...arguments);
} else {
const order = this.env.pos.get_order();
if (order) {
const { name: screenName } = order.get_screen_data();
this.pos.showScreen(screenName);
} else {
this.pos.showScreen("FloorScreen");
}
}
},
_getScreenToStatusMap() {
return Object.assign(this._super(...arguments), {
PaymentScreen: this.env.pos.config.set_tip_after_payment
@@ -56,7 +43,7 @@ patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", {
this.close();
}
},
shouldShowNewOrderButton() {
get allowNewOrders() {
return this.env.pos.config.iface_floorplan
? Boolean(this.env.pos.table)
: this._super(...arguments);
@@ -176,7 +163,7 @@ patch(TicketScreen.prototype, "pos_restaurant.TicketScreen", {
},
});
export class TipCell extends PosComponent {
export class TipCell extends LegacyComponent {
static template = "TipCell";
setup() {
@@ -1,6 +1,6 @@
/** @odoo-module */
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { parse } from "web.field_utils";
import { renderToString } from "@web/core/utils/render";
import { registry } from "@web/core/registry";
@@ -11,7 +11,7 @@ import { useService } from "@web/core/utils/hooks";
const { onMounted } = owl;
export class TipScreen extends PosComponent {
export class TipScreen extends LegacyComponent {
static template = "pos_restaurant.TipScreen";
static showBackToFloorButton = true;
setup() {
@@ -9,6 +9,7 @@ import { registry } from "@web/core/registry";
startSteps();
ProductScreen.do.confirmOpeningPopup();
// New Ticket button should not be in the ticket screen if no table is selected.
Chrome.do.clickTicketButton();
TicketScreen.check.noNewTicketButton();
@@ -16,7 +17,6 @@ TicketScreen.do.clickDiscard();
// Deleting the last order in the table brings back to floorscreen
FloorScreen.do.clickTable("T4");
ProductScreen.do.confirmOpeningPopup();
ProductScreen.check.isShown();
Chrome.do.clickTicketButton();
TicketScreen.check.nthRowContains(2, "-0001");
@@ -58,4 +58,6 @@ FloorScreen.check.orderCountSyncedInTableIs("T5", "0");
FloorScreen.do.clickTable("T5");
ProductScreen.check.orderIsEmpty();
registry.category("web_tour.tours").add("PosResTicketScreenTour", { test: true, url: "/pos/ui", steps: getSteps() });
registry
.category("web_tour.tours")
.add("PosResTicketScreenTour", { test: true, url: "/pos/ui", steps: getSteps() });
@@ -1,15 +1,17 @@
/** @odoo-module */
import { Gui } from "@point_of_sale/js/Gui";
import { registry } from "@web/core/registry";
import { EventBus } from "@odoo/owl";
const { EventBus } = owl;
// FIXME POSREF: should probably be a service instead of a singleton.
class SaleOrderFetcher extends EventBus {
constructor() {
static serviceDependencies = ["orm", "pos"];
constructor({ orm, pos }) {
super();
this.currentPage = 1;
this.ordersToShow = [];
this.totalCount = 0;
this.orm = orm;
this.pos = pos;
}
/**
@@ -59,28 +61,27 @@ class SaleOrderFetcher extends EventBus {
return sale_orders;
}
async _getOrderIdsForCurrentPage(limit, offset) {
const domain = [["currency_id", "=", this.comp.env.pos.currency.id]].concat(
this.searchDomain || []
);
return await this.rpc({
model: "sale.order",
method: "search_read",
args: [
domain,
[
"name",
"partner_id",
"amount_total",
"date_order",
"state",
"user_id",
"amount_unpaid",
],
offset,
limit,
const domain = [["currency_id", "=", this.pos.globalState.currency.id]];
if (this.searchDomain) {
domain.push(...this.searchDomain);
}
this.pos.globalState.set_synch("connecting");
const res = await this.orm.searchRead(
"sale.order",
domain,
[
"name",
"partner_id",
"amount_total",
"date_order",
"state",
"user_id",
"amount_unpaid",
],
context: this.comp.env.session.user_context,
});
{ offset, limit }
);
this.pos.globalState.set_synch("connected");
return res;
}
nextPage() {
@@ -105,23 +106,19 @@ class SaleOrderFetcher extends EventBus {
setSearchDomain(searchDomain) {
this.searchDomain = searchDomain;
}
setComponent(comp) {
this.comp = comp;
return this;
}
setNPerPage(val) {
this.nPerPage = val;
}
setPage(page) {
this.currentPage = page;
}
async rpc() {
Gui.setSyncStatus("connecting");
const result = await this.comp.rpc(...arguments);
Gui.setSyncStatus("connected");
return result;
}
}
export const saleOrderFetcher = new SaleOrderFetcher();
export const saleOrderFetcherService = {
dependencies: SaleOrderFetcher.serviceDependencies,
start(env, deps) {
return new SaleOrderFetcher(deps);
},
};
registry.category("services").add("sale_order_fetcher", saleOrderFetcherService);
@@ -1,7 +1,7 @@
/** @odoo-module */
import { useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { SaleOrderRow } from "./SaleOrderRow";
@@ -11,7 +11,7 @@ const { useState } = owl;
* @props {models.Order} [initHighlightedOrder] initially highligted order
* @props {Array<models.Order>} orders
*/
export class SaleOrderList extends PosComponent {
export class SaleOrderList extends LegacyComponent {
static components = { SaleOrderRow };
static template = "SaleOrderList";
@@ -1,8 +1,7 @@
/** @odoo-module */
import { useAutofocus, useListener } from "@web/core/utils/hooks";
import { PosComponent } from "@point_of_sale/js/PosComponent";
import { saleOrderFetcher } from "@pos_sale/js/OrderManagementScreen/SaleOrderFetcher";
import { useAutofocus, useListener, useService } from "@web/core/utils/hooks";
import { LegacyComponent } from "@web/legacy/legacy_component";
import { orderManagement } from "@point_of_sale/js/PosContext";
const { useState } = owl;
@@ -25,11 +24,12 @@ const SEARCH_FIELDS = ["name", "partner_id.display_name", "date_order"];
* @emits next-page
* @emits search
*/
export class SaleOrderManagementControlPanel extends PosComponent {
export class SaleOrderManagementControlPanel extends LegacyComponent {
static template = "SaleOrderManagementControlPanel";
setup() {
super.setup();
this.saleOrderFetcher = useService("sale_order_fetcher");
this.orderManagementContext = useState(orderManagement);
useListener("clear-search", this._onClearSearch);
useAutofocus();
@@ -38,7 +38,7 @@ export class SaleOrderManagementControlPanel extends PosComponent {
if (currentPartner) {
this.orderManagementContext.searchString = currentPartner.name;
}
saleOrderFetcher.setSearchDomain(this._computeDomain());
this.saleOrderFetcher.setSearchDomain(this._computeDomain());
}
onInputKeydown(event) {
if (event.key === "Enter") {
@@ -46,11 +46,11 @@ export class SaleOrderManagementControlPanel extends PosComponent {
}
}
get showPageControls() {
return saleOrderFetcher.lastPage > 1;
return this.saleOrderFetcher.lastPage > 1;
}
get pageNumber() {
const currentPage = saleOrderFetcher.currentPage;
const lastPage = saleOrderFetcher.lastPage;
const currentPage = this.saleOrderFetcher.currentPage;
const lastPage = this.saleOrderFetcher.lastPage;
return isNaN(lastPage) ? "" : `(${currentPage}/${lastPage})`;
}
get validSearchTags() {
@@ -2,10 +2,9 @@
import { sprintf } from "web.utils";
import { parse } from "web.field_utils";
import { useListener, useService } from "@web/core/utils/hooks";
import { useBus, useListener, useService } from "@web/core/utils/hooks";
import { registry } from "@web/core/registry";
import { ControlButtonsMixin } from "@point_of_sale/js/ControlButtonsMixin";
import { saleOrderFetcher } from "@pos_sale/js/OrderManagementScreen/SaleOrderFetcher";
import { IndependentToOrderScreen } from "@point_of_sale/js/Misc/IndependentToOrderScreen";
import { orderManagement } from "@point_of_sale/js/PosContext";
import { Orderline } from "@point_of_sale/js/models";
@@ -18,7 +17,7 @@ import { NumberPopup } from "@point_of_sale/js/Popups/NumberPopup";
import { SaleOrderList } from "./SaleOrderList";
import { SaleOrderManagementControlPanel } from "./SaleOrderManagementControlPanel";
const { onMounted, onWillUnmount, useState } = owl;
const { onMounted, useState } = owl;
export class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentToOrderScreen) {
static components = { SaleOrderList, SaleOrderManagementControlPanel };
@@ -28,21 +27,19 @@ export class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentTo
super.setup();
this.popup = useService("popup");
this.numberBuffer = useService("number_buffer");
this.saleOrderFetcher = useService("sale_order_fetcher");
useListener("close-screen", this.close);
useListener("click-sale-order", this._onClickSaleOrder);
useListener("next-page", this._onNextPage);
useListener("prev-page", this._onPrevPage);
useListener("search", this._onSearch);
saleOrderFetcher.setComponent(this);
useBus(this.saleOrderFetcher, "update", this.render);
this.orderManagementContext = useState(orderManagement);
onMounted(this.onMounted);
onWillUnmount(this.onWillUnmount);
}
onMounted() {
saleOrderFetcher.on("update", this, this.render);
// calculate how many can fit in the screen.
// It is based on the height of the header element.
// So the result is only accurate if each row is just single line.
@@ -53,21 +50,15 @@ export class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentTo
(flexContainer.offsetHeight - cpEl.offsetHeight - headerEl.offsetHeight) /
headerEl.offsetHeight
);
saleOrderFetcher.setNPerPage(val);
// Fetch the order after mounting so that order management screen
// is shown while fetching.
setTimeout(() => saleOrderFetcher.fetch(), 0);
}
onWillUnmount() {
saleOrderFetcher.off("update", this);
this.saleOrderFetcher.setNPerPage(val);
this.saleOrderFetcher.fetch();
}
get selectedPartner() {
const order = this.orderManagementContext.selectedOrder;
return order ? order.get_partner() : null;
}
get orders() {
return saleOrderFetcher.get();
return this.saleOrderFetcher.get();
}
async _setNumpadMode(event) {
const { mode } = event.detail;
@@ -75,15 +66,15 @@ export class SaleOrderManagementScreen extends ControlButtonsMixin(IndependentTo
this.numberBuffer.reset();
}
_onNextPage() {
saleOrderFetcher.nextPage();
this.saleOrderFetcher.nextPage();
}
_onPrevPage() {
saleOrderFetcher.prevPage();
this.saleOrderFetcher.prevPage();
}
_onSearch({ detail: domain }) {
saleOrderFetcher.setSearchDomain(domain);
saleOrderFetcher.setPage(1);
saleOrderFetcher.fetch();
this.saleOrderFetcher.setSearchDomain(domain);
this.saleOrderFetcher.setPage(1);
this.saleOrderFetcher.fetch();
}
async _onClickSaleOrder(event) {
const clickedOrder = event.detail;

Some files were not shown because too many files have changed in this diff Show More