[REF] pos*: merge PosStore and PosGlobalState
*: l10n_ae_pos, l10n_co_pos, l10n_fr_pos_cert, l10n_gcc_pos, l10n_in_pos, point_of_sale, pos_adyen, pos_discount, pos_epson_printer, pos_hr, pos_loyalty, pos_mercury, pos_restaurant, pos_sale, pos_sale_product_configurator, pos_six, pos_stripe After the architectural refactor of the PoS App, there are two classes that make sense to merge. In this refactoring task, we're merging them. closes odoo/odoo#124477 Task: 3358550 Related: odoo/enterprise#42257 Signed-off-by: Joseph Caburnay (jcb) <jcb@odoo.com>
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<t t-name="l10n_ae_pos.OrderReceiptVAT" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[@id='post_receipt_taxes_container']" position="replace">
|
||||
<div id='post_receipt_taxes_container'>
|
||||
<t t-if="pos.globalState.company.country.code == 'AE'">VAT</t>
|
||||
<t t-if="pos.company.country.code == 'AE'">VAT</t>
|
||||
<t t-else="">Total Taxes</t>
|
||||
<span t-esc="env.utils.formatCurrency(receipt.total_tax)" class="pos-receipt-right-align"/>
|
||||
</div>
|
||||
|
||||
@@ -7,7 +7,7 @@ patch(PaymentScreen.prototype, "l10n_co_pos.PaymentScreen", {
|
||||
async _postPushOrderResolve(order, order_server_ids) {
|
||||
const _super = this._super;
|
||||
try {
|
||||
if (this.pos.globalState.is_colombian_country()) {
|
||||
if (this.pos.is_colombian_country()) {
|
||||
const result = await this.orm.searchRead(
|
||||
"pos.order",
|
||||
[["id", "in", order_server_ids]],
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { PosGlobalState, Order } from "@point_of_sale/app/store/models";
|
||||
import { PosStore } from "@point_of_sale/app/store/pos_store";
|
||||
import { Order } from "@point_of_sale/app/store/models";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(PosGlobalState.prototype, "l10n_co_pos.PosGlobalState", {
|
||||
patch(PosStore.prototype, "l10n_co_pos.PosStore", {
|
||||
is_colombian_country() {
|
||||
return this.company.country.code === "CO";
|
||||
},
|
||||
|
||||
@@ -9,13 +9,12 @@ patch(Chrome.prototype, "l10n_fr_pos_cert.Chrome", {
|
||||
setup() {
|
||||
this._super(...arguments);
|
||||
onMounted(async () => {
|
||||
const { globalState } = this.pos;
|
||||
if (globalState.is_french_country() && globalState.pos_session.start_at) {
|
||||
if (this.pos.is_french_country() && this.pos.pos_session.start_at) {
|
||||
const now = Date.now();
|
||||
const limitDate = new Date(globalState.pos_session.start_at);
|
||||
const limitDate = new Date(this.pos.pos_session.start_at);
|
||||
limitDate.setDate(limitDate.getDate() + 1);
|
||||
if (limitDate.getTime() < now) {
|
||||
const info = await globalState.getClosePosInfo();
|
||||
const info = await this.pos.getClosePosInfo();
|
||||
this.popup.add(ClosePosPopup, { info });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ patch(PaymentScreen.prototype, "l10n_fr_pos_cert.PaymentScreen", {
|
||||
async _postPushOrderResolve(order, order_server_ids) {
|
||||
const _super = this._super;
|
||||
try {
|
||||
if (this.pos.globalState.is_french_country()) {
|
||||
if (this.pos.is_french_country()) {
|
||||
const result = await this.orm.searchRead(
|
||||
"pos.order",
|
||||
[["id", "in", order_server_ids]],
|
||||
|
||||
@@ -6,9 +6,9 @@ import { patch } from "@web/core/utils/patch";
|
||||
patch(ClosePosPopup.prototype, "l10n_fr_pos_cert.ClosePosPopup", {
|
||||
sessionIsOutdated() {
|
||||
let isOutdated = false;
|
||||
if (this.pos.globalState.is_french_country() && this.pos.globalState.pos_session.start_at) {
|
||||
if (this.pos.is_french_country() && this.pos.pos_session.start_at) {
|
||||
const now = Date.now();
|
||||
const limitDate = new Date(this.pos.globalState.pos_session.start_at);
|
||||
const limitDate = new Date(this.pos.pos_session.start_at);
|
||||
limitDate.setDate(limitDate.getDate() + 1);
|
||||
isOutdated = limitDate < now;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { PosGlobalState, Order, Orderline } from "@point_of_sale/app/store/models";
|
||||
import { PosStore } from "@point_of_sale/app/store/pos_store";
|
||||
import { Order, Orderline } from "@point_of_sale/app/store/models";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
|
||||
|
||||
patch(PosGlobalState.prototype, "l10n_fr_pos_cert.PosGlobalState", {
|
||||
patch(PosStore.prototype, "l10n_fr_pos_cert.PosStore", {
|
||||
is_french_country() {
|
||||
var french_countries = ["FR", "MF", "MQ", "NC", "PF", "RE", "GF", "GP", "TF"];
|
||||
if (!this.company.country) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="l10n_fr_pos_cert.Orderline" t-inherit="point_of_sale.Orderline" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//ul[hasclass('info-list')]" position="inside">
|
||||
<t t-if="pos.globalState.is_french_country() !== false and props.line.price_type === 'manual'">
|
||||
<t t-if="pos.is_french_country() !== false and props.line.price_manually_set === 'manual'">
|
||||
<li class="info">
|
||||
Old unit price:
|
||||
<span class="oldPrice">
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
<xpath expr="//t[@t-esc='line.unit_name']/.." position="after">
|
||||
<t t-if="receipt.is_gcc_country">
|
||||
<div class="pos-receipt-left-padding">
|
||||
<t t-esc="Math.round(line.quantity * Math.pow(10, pos.globalState.dp['Product Unit of Measure'])) / Math.pow(10, pos.globalState.dp['Product Unit of Measure'])"/>
|
||||
<t t-esc="Math.round(line.quantity * Math.pow(10, pos.dp['Product Unit of Measure'])) / Math.pow(10, pos.dp['Product Unit of Measure'])"/>
|
||||
<t t-if="!line.is_in_unit" t-esc="line.unit_name" />
|
||||
x
|
||||
<t t-esc="env.utils.formatCurrency(line.price_display_one, false)" />
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
<t t-name="l10n_in_pos.OrderReceipt" t-inherit="point_of_sale.OrderReceipt" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//div[hasclass('orderlines')]" position="before">
|
||||
<t t-if="receipt.partner and pos.globalState.company.country and pos.globalState.company.country.code == 'IN'">
|
||||
<t t-if="receipt.partner and pos.company.country and pos.company.country.code == 'IN'">
|
||||
<div class="pos-receipt-center-align">
|
||||
<div><t t-esc="receipt.partner.name" /></div>
|
||||
<t t-if="receipt.partner.phone">
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<t t-name="l10n_in_pos.OrderLinesReceipt" t-inherit="point_of_sale.OrderLinesReceipt" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//t[@t-foreach='receipt.orderlines']" position="inside">
|
||||
<t t-if="line.l10n_in_hsn_code and pos.globalState.company.country and pos.globalState.company.country.code == 'IN'">
|
||||
<t t-if="line.l10n_in_hsn_code and pos.company.country and pos.company.country.code == 'IN'">
|
||||
<div class="pos-receipt-left-padding">
|
||||
<span>HSN Code: </span>
|
||||
<t t-esc="line.l10n_in_hsn_code"/>
|
||||
|
||||
@@ -14,7 +14,7 @@ export class PosBus {
|
||||
this.orm = orm;
|
||||
|
||||
// initialize bus_service and listen on pos_config-`id` channel
|
||||
bus_service.addChannel(`pos_config-${pos.globalState.config.id}`);
|
||||
bus_service.addChannel(`pos_config-${pos.config.id}`);
|
||||
bus_service.addEventListener("notification", ({ detail }) => {
|
||||
for (const message of detail) {
|
||||
this.dispatch(message);
|
||||
|
||||
@@ -11,8 +11,8 @@ export class LocalDisplay extends Reactive {
|
||||
super();
|
||||
this.setup(...arguments);
|
||||
}
|
||||
setup(globalState) {
|
||||
this.globalState = globalState;
|
||||
setup(pos) {
|
||||
this.pos = pos;
|
||||
}
|
||||
async connect() {
|
||||
if (this.popupWindow && !this.popupWindow.closed) {
|
||||
@@ -59,7 +59,7 @@ export class LocalDisplay extends Reactive {
|
||||
// animations.
|
||||
const { body: displayBody, head: displayHead } = this.popupWindow.document;
|
||||
const container = document.createElement("div");
|
||||
container.innerHTML = await this.globalState.customerDisplayHTML(closeUI);
|
||||
container.innerHTML = await this.pos.customerDisplayHTML(closeUI);
|
||||
|
||||
if (!container.innerHTML || container.innerHTML === "undefined") {
|
||||
displayBody.textContent = "";
|
||||
@@ -95,13 +95,13 @@ export class RemoteDisplay extends Reactive {
|
||||
super();
|
||||
this.setup(...arguments);
|
||||
}
|
||||
setup(globalState, { hardware_proxy }) {
|
||||
setup(pos, { hardware_proxy }) {
|
||||
this.hardwareProxy = hardware_proxy;
|
||||
this.globalState = globalState;
|
||||
this.pos = pos;
|
||||
this.updateStatus();
|
||||
}
|
||||
async connect() {
|
||||
const html = await this.globalState.customerDisplayHTML();
|
||||
const html = await this.pos.customerDisplayHTML();
|
||||
try {
|
||||
const { status } = await this.hardwareProxy.message("take_control", { html });
|
||||
this.status = status === "success" ? "success" : "warning";
|
||||
@@ -111,7 +111,7 @@ export class RemoteDisplay extends Reactive {
|
||||
}
|
||||
}
|
||||
async update({ closeUI = false } = {}) {
|
||||
const html = await this.globalState.customerDisplayHTML(closeUI);
|
||||
const html = await this.pos.customerDisplayHTML(closeUI);
|
||||
if (this.isUpdatingStatus && this.hardwareProxy.connectionInfo.status === "connected") {
|
||||
return this.hardwareProxy.message("customer_facing_display", { html });
|
||||
}
|
||||
@@ -147,19 +147,19 @@ export const customerDisplayService = {
|
||||
return ["pos", ...RemoteDisplay.serviceDependencies];
|
||||
},
|
||||
start(env, deps) {
|
||||
const { globalState } = deps.pos;
|
||||
const pos = deps.pos;
|
||||
|
||||
const {
|
||||
iface_customer_facing_display: enabled,
|
||||
iface_customer_facing_display_via_proxy: proxy,
|
||||
} = globalState.config;
|
||||
} = pos.config;
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const display = proxy
|
||||
? new RemoteDisplay(globalState, pick(deps, ...RemoteDisplay.serviceDependencies))
|
||||
: new LocalDisplay(globalState);
|
||||
? new RemoteDisplay(pos, pick(deps, ...RemoteDisplay.serviceDependencies))
|
||||
: new LocalDisplay(pos);
|
||||
// Register an effect to update the display automatically when anything it renders changes
|
||||
effect(
|
||||
batched((display) => display.update()),
|
||||
|
||||
@@ -97,8 +97,8 @@ export class DebugWidget extends Component {
|
||||
),
|
||||
});
|
||||
if (confirmed) {
|
||||
this.pos.globalState.db.remove_all_orders();
|
||||
this.pos.globalState.set_synch("connected", 0);
|
||||
this.pos.db.remove_all_orders();
|
||||
this.pos.set_synch("connected", 0);
|
||||
}
|
||||
}
|
||||
async deleteUnpaidOrders() {
|
||||
@@ -109,7 +109,7 @@ export class DebugWidget extends Component {
|
||||
),
|
||||
});
|
||||
if (confirmed) {
|
||||
this.pos.globalState.db.remove_all_unpaid_orders();
|
||||
this.pos.db.remove_all_unpaid_orders();
|
||||
window.location = "/";
|
||||
}
|
||||
}
|
||||
@@ -123,7 +123,7 @@ export class DebugWidget extends Component {
|
||||
// The implementation can be better.
|
||||
preparePaidOrders() {
|
||||
try {
|
||||
this.paidOrdersBlob = this._createBlob(this.pos.globalState.export_paid_orders());
|
||||
this.paidOrdersBlob = this._createBlob(this.pos.export_paid_orders());
|
||||
this.state.isPaidOrdersReady = true;
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
@@ -139,7 +139,7 @@ export class DebugWidget extends Component {
|
||||
// FIXME POSREF why is this two steps?
|
||||
prepareUnpaidOrders() {
|
||||
try {
|
||||
this.unpaidOrdersBlob = this._createBlob(this.pos.globalState.export_unpaid_orders());
|
||||
this.unpaidOrdersBlob = this._createBlob(this.pos.export_unpaid_orders());
|
||||
this.state.isUnpaidOrdersReady = true;
|
||||
} catch (error) {
|
||||
console.warn(error);
|
||||
@@ -155,7 +155,7 @@ export class DebugWidget extends Component {
|
||||
async importOrders(event) {
|
||||
const file = event.target.files[0];
|
||||
if (file) {
|
||||
const report = this.pos.globalState.import_orders(await file.text());
|
||||
const report = this.pos.import_orders(await file.text());
|
||||
await this.popup.add(OrderImportPopup, { report });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ export class ErrorTracebackPopup extends ErrorPopup {
|
||||
return `${this.env._t("error")} ${moment().format("YYYY-MM-DD-HH-mm-ss")}.txt`;
|
||||
}
|
||||
emailTraceback() {
|
||||
const address = this.pos.globalState.company.email;
|
||||
const address = this.pos.company.email;
|
||||
const subject = this.env._t("IMPORTANT: Bug Report From Odoo Point Of Sale");
|
||||
window.open(
|
||||
"mailto:" +
|
||||
|
||||
@@ -22,15 +22,15 @@ export class OfflineErrorPopup extends ErrorPopup {
|
||||
super.setup(...arguments);
|
||||
this.pos = usePos();
|
||||
|
||||
if (!this.pos.globalState.showOfflineWarning) {
|
||||
if (!this.pos.showOfflineWarning) {
|
||||
this.cancel();
|
||||
} else {
|
||||
this.pos.globalState.set_synch("disconnected");
|
||||
this.pos.set_synch("disconnected");
|
||||
}
|
||||
}
|
||||
|
||||
confirm() {
|
||||
this.pos.globalState.showOfflineWarning = false;
|
||||
this.pos.showOfflineWarning = false;
|
||||
this.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ export class BackButton extends Component {
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
async backToFloorScreen() {
|
||||
this.pos.globalState.mobile_pane = "right";
|
||||
this.pos.mobile_pane = "right";
|
||||
this.pos.showScreen("ProductScreen");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,13 +59,13 @@ export class CashMovePopup extends AbstractAwaitablePopup {
|
||||
const extras = { formattedAmount, translatedType };
|
||||
const reason = this.state.reason.trim();
|
||||
await this.orm.call("pos.session", "try_cash_in_out", [
|
||||
[this.pos.globalState.pos_session.id],
|
||||
[this.pos.pos_session.id],
|
||||
type,
|
||||
amount,
|
||||
reason,
|
||||
extras,
|
||||
]);
|
||||
await this.pos.globalState.logEmployeeMessage(
|
||||
await this.pos.logEmployeeMessage(
|
||||
`${_t("Cash")} ${translatedType} - ${_t("Amount")}: ${formattedAmount}`,
|
||||
"CASH_DRAWER_ACTION"
|
||||
);
|
||||
@@ -78,8 +78,8 @@ export class CashMovePopup extends AbstractAwaitablePopup {
|
||||
amount,
|
||||
translatedType,
|
||||
formattedAmount,
|
||||
cashier: this.pos.globalState.get_cashier(),
|
||||
company: this.pos.globalState.company,
|
||||
cashier: this.pos.get_cashier(),
|
||||
company: this.pos.company,
|
||||
},
|
||||
});
|
||||
const printResult = await this.hardwareProxy.printer.printReceipt(renderedReceipt);
|
||||
@@ -116,10 +116,10 @@ export class CashMovePopup extends AbstractAwaitablePopup {
|
||||
async cancel() {
|
||||
super.cancel();
|
||||
if (
|
||||
this.pos.globalState.config.iface_cashdrawer &&
|
||||
this.pos.globalState.hardwareProxy.connectionInfo.status === "connected"
|
||||
this.pos.config.iface_cashdrawer &&
|
||||
this.pos.hardwareProxy.connectionInfo.status === "connected"
|
||||
) {
|
||||
this.pos.globalState.logEmployeeMessage(_t("Cash in / out"), "ACTION_CANCELLED");
|
||||
this.pos.logEmployeeMessage(_t("Cash in / out"), "ACTION_CANCELLED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,11 +14,11 @@
|
||||
</span>
|
||||
<div class="input-field">
|
||||
<input type="text" name="amount" t-model="state.amount" t-ref="amountInput" t-on-keypress="_onAmountKeypress"/>
|
||||
<t t-if="pos.globalState.currency.symbol.length > 1">
|
||||
<span class="left-currency" t-esc="pos.globalState.currency.symbol" />
|
||||
<t t-if="pos.currency.symbol.length > 1">
|
||||
<span class="left-currency" t-esc="pos.currency.symbol" />
|
||||
</t>
|
||||
<t t-else="">
|
||||
<span class="currency" t-esc="pos.globalState.currency.symbol" />
|
||||
<span class="currency" t-esc="pos.currency.symbol" />
|
||||
</t>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,11 +13,11 @@ export class CashierName extends Component {
|
||||
this.ui = useState(useService("ui"));
|
||||
}
|
||||
get username() {
|
||||
const { name } = this.pos.globalState.get_cashier();
|
||||
const { name } = this.pos.get_cashier();
|
||||
return name ? name : "";
|
||||
}
|
||||
get avatar() {
|
||||
const user_id = this.pos.globalState.get_cashier_user_id();
|
||||
const user_id = this.pos.get_cashier_user_id();
|
||||
const id = user_id ? user_id : -1;
|
||||
return `/web/image/res.users/${id}/avatar_128`;
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
this.hardwareProxy = useService("hardware_proxy");
|
||||
this.customerDisplay = useService("customer_display");
|
||||
this.manualInputCashCount = false;
|
||||
this.cashControl = this.pos.globalState.config.cash_control;
|
||||
this.cashControl = this.pos.config.cash_control;
|
||||
this.closeSessionClicked = false;
|
||||
this.moneyDetails = null;
|
||||
Object.assign(this, this.props.info);
|
||||
@@ -97,7 +97,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
}
|
||||
async downloadSalesReport() {
|
||||
return this.report.download("point_of_sale.sale_details_report", [
|
||||
this.pos.globalState.pos_session.id,
|
||||
this.pos.pos_session.id,
|
||||
]);
|
||||
}
|
||||
handleInputChange(paymentId) {
|
||||
@@ -142,7 +142,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
const response = await this.orm.call(
|
||||
"pos.session",
|
||||
"post_closing_cash_details",
|
||||
[this.pos.globalState.pos_session.id],
|
||||
[this.pos.pos_session.id],
|
||||
{
|
||||
counted_cash: this.state.payments[this.defaultCashDetails.id].counted,
|
||||
}
|
||||
@@ -155,7 +155,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
|
||||
try {
|
||||
await this.orm.call("pos.session", "update_closing_control_state_session", [
|
||||
this.pos.globalState.pos_session.id,
|
||||
this.pos.pos_session.id,
|
||||
this.state.notes,
|
||||
]);
|
||||
} catch (error) {
|
||||
@@ -176,7 +176,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
|
||||
.filter((pm) => pm.type == "bank")
|
||||
.map((pm) => [pm.id, this.state.payments[pm.id].difference]);
|
||||
const response = await this.orm.call("pos.session", "close_session_from_ui", [
|
||||
this.pos.globalState.pos_session.id,
|
||||
this.pos.pos_session.id,
|
||||
bankPaymentMethodDiffPairs,
|
||||
]);
|
||||
if (!response.successful) {
|
||||
|
||||
@@ -45,10 +45,10 @@ export class Navbar extends Component {
|
||||
}
|
||||
|
||||
get customerFacingDisplayButtonIsShown() {
|
||||
return this.pos.globalState.config.iface_customer_facing_display;
|
||||
return this.pos.config.iface_customer_facing_display;
|
||||
}
|
||||
get showCashMoveButton() {
|
||||
return Boolean(this.pos.globalState?.config?.cash_control);
|
||||
return Boolean(this.pos?.config?.cash_control);
|
||||
}
|
||||
onCashMoveButtonClick() {
|
||||
this.hardwareProxy.openCashbox(_t("Cash in / out"));
|
||||
@@ -59,15 +59,14 @@ export class Navbar extends Component {
|
||||
this.pos.closeScreen();
|
||||
} else {
|
||||
if (this._shouldLoadOrders()) {
|
||||
const { globalState } = this.pos;
|
||||
try {
|
||||
globalState.setLoadingOrderState(true);
|
||||
const message = await globalState._syncAllOrdersFromServer();
|
||||
this.pos.setLoadingOrderState(true);
|
||||
const message = await this.pos._syncAllOrdersFromServer();
|
||||
if (message) {
|
||||
this.notification.add(message, 5000);
|
||||
}
|
||||
} finally {
|
||||
globalState.setLoadingOrderState(false);
|
||||
this.pos.setLoadingOrderState(false);
|
||||
this.pos.showScreen("TicketScreen");
|
||||
}
|
||||
} else {
|
||||
@@ -77,7 +76,7 @@ export class Navbar extends Component {
|
||||
}
|
||||
|
||||
_shouldLoadOrders() {
|
||||
return this.pos.globalState.config.trusted_config_ids.length > 0;
|
||||
return this.pos.config.trusted_config_ids.length > 0;
|
||||
}
|
||||
|
||||
get isTicketScreenShown() {
|
||||
@@ -85,7 +84,7 @@ export class Navbar extends Component {
|
||||
}
|
||||
|
||||
get orderCount() {
|
||||
return this.pos.globalState.get_order_list().length;
|
||||
return this.pos.get_order_list().length;
|
||||
}
|
||||
|
||||
isBurgerMenuClosed() {
|
||||
@@ -101,7 +100,7 @@ export class Navbar extends Component {
|
||||
}
|
||||
|
||||
async closeSession() {
|
||||
const info = await this.pos.globalState.getClosePosInfo();
|
||||
const info = await this.pos.getClosePosInfo();
|
||||
this.popup.add(ClosePosPopup, { info, keepBehind: true });
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<div class="status-buttons">
|
||||
<CashierName />
|
||||
<SaleDetailsButton t-if="hardwareProxy.printer" isHeaderButton="true"/>
|
||||
<ProxyStatus t-if="pos.globalState.config.use_proxy" />
|
||||
<ProxyStatus t-if="pos.config.use_proxy" />
|
||||
<CustomerFacingDisplayButton t-if="customerFacingDisplayButtonIsShown" />
|
||||
<SyncNotification />
|
||||
</div>
|
||||
|
||||
@@ -24,7 +24,7 @@ export class ProxyStatus extends Component {
|
||||
iface_print_via_proxy,
|
||||
iface_cashdrawer,
|
||||
iface_electronic_scale,
|
||||
} = this.pos.globalState.config;
|
||||
} = this.pos.config;
|
||||
const devices = [
|
||||
{
|
||||
name: _t("Scanner"),
|
||||
|
||||
+2
-3
@@ -18,20 +18,19 @@ export class SaleDetailsButton extends Component {
|
||||
}
|
||||
|
||||
async onClick() {
|
||||
const { globalState } = this.pos;
|
||||
// IMPROVEMENT: Perhaps put this logic in a parent component
|
||||
// so that for unit testing, we can check if this simple
|
||||
// component correctly triggers an event.
|
||||
const saleDetails = await this.orm.call(
|
||||
"report.point_of_sale.report_saledetails",
|
||||
"get_sale_details",
|
||||
[false, false, false, [globalState.pos_session.id]]
|
||||
[false, false, false, [this.pos.pos_session.id]]
|
||||
);
|
||||
const report = renderToElement(
|
||||
"point_of_sale.SaleDetailsReport",
|
||||
Object.assign({}, saleDetails, {
|
||||
date: new Date().toLocaleString(),
|
||||
pos: globalState,
|
||||
pos: this.pos,
|
||||
formatCurrency: this.env.utils.formatCurrency,
|
||||
})
|
||||
);
|
||||
|
||||
@@ -10,12 +10,12 @@ export class SyncNotification extends Component {
|
||||
this.pos = usePos();
|
||||
}
|
||||
get sync() {
|
||||
return this.pos.globalState.synch;
|
||||
return this.pos.synch;
|
||||
}
|
||||
onClick() {
|
||||
if (this.pos.globalState.synch.status !== "connected") {
|
||||
this.pos.globalState.showOfflineWarning = true;
|
||||
if (this.pos.synch.status !== "connected") {
|
||||
this.pos.showOfflineWarning = true;
|
||||
}
|
||||
this.pos.globalState.push_orders({ show_error: true });
|
||||
this.pos.push_orders({ show_error: true });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
*
|
||||
* To connect the interface to the right payment methods register it:
|
||||
*
|
||||
* import { register_payment_method } models from "@point_of_sale/app/store/models";
|
||||
* import { register_payment_method } models from "@point_of_sale/app/store/pos_store";
|
||||
* register_payment_method('my_payment', MyPayment);
|
||||
*
|
||||
* my_payment is the technical name of the added selection in
|
||||
|
||||
@@ -19,7 +19,7 @@ export class Chrome extends Component {
|
||||
this.pos = usePos();
|
||||
this.popup = useService("popup");
|
||||
|
||||
const reactivePos = reactive(this.pos.globalState);
|
||||
const reactivePos = reactive(this.pos);
|
||||
// TODO: Should we continue on exposing posmodel as global variable?
|
||||
window.posmodel = reactivePos;
|
||||
|
||||
@@ -33,6 +33,11 @@ export class Chrome extends Component {
|
||||
onMounted(this.props.disableLoader);
|
||||
}
|
||||
|
||||
// GETTERS //
|
||||
|
||||
get showCashMoveButton() {
|
||||
return Boolean(this.pos?.config?.cash_control);
|
||||
}
|
||||
/**
|
||||
* Unmounts the tempScreen on error and dispatches the error in a separate
|
||||
* stack so that it can be handled by the error service and display an error
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ export class PartnerDetailsEdit extends Component {
|
||||
if (partner.property_product_pricelist) {
|
||||
return partner.property_product_pricelist[0];
|
||||
}
|
||||
return this.pos.globalState.default_pricelist?.id ?? false;
|
||||
return this.pos.default_pricelist?.id ?? false;
|
||||
}
|
||||
|
||||
get partnerImageUrl() {
|
||||
|
||||
+7
-7
@@ -40,7 +40,7 @@
|
||||
<select class="detail" name="state_id"
|
||||
t-on-change="captureChange">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="pos.globalState.states" t-as="state" t-key="state.id">
|
||||
<t t-foreach="pos.states" t-as="state" t-key="state.id">
|
||||
<option t-if="props.partner.country_id[0] == state.country_id[0]"
|
||||
t-att-value="state.id"
|
||||
t-att-selected="props.partner.state_id ? ((state.id === props.partner.state_id[0]) ? true : undefined) : undefined">
|
||||
@@ -54,7 +54,7 @@
|
||||
<select class="detail" name="country_id"
|
||||
t-on-change="captureChange">
|
||||
<option value="">None</option>
|
||||
<t t-foreach="pos.globalState.countries" t-as="country" t-key="country.id">
|
||||
<t t-foreach="pos.countries" t-as="country" t-key="country.id">
|
||||
<option t-att-value="country.id"
|
||||
t-att-selected="props.partner.country_id ? ((country.id === props.partner.country_id[0]) ? true : undefined) : undefined">
|
||||
<t t-esc="country.name" />
|
||||
@@ -68,9 +68,9 @@
|
||||
<span class="label">Language</span>
|
||||
<select class="detail" name="lang"
|
||||
t-on-change="captureChange">
|
||||
<t t-foreach="pos.globalState.langs" t-as="lang" t-key="lang.id">
|
||||
<t t-foreach="pos.langs" t-as="lang" t-key="lang.id">
|
||||
<option t-att-value="lang.code"
|
||||
t-att-selected="props.partner.lang ? ((lang.code === props.partner.lang) ? true : undefined) : lang.code === pos.globalState.user.lang? true : undefined">
|
||||
t-att-selected="props.partner.lang ? ((lang.code === props.partner.lang) ? true : undefined) : lang.code === pos.user.lang? true : undefined">
|
||||
<t t-esc="lang.name" />
|
||||
</option>
|
||||
</t>
|
||||
@@ -104,14 +104,14 @@
|
||||
<input class="detail vat" name="vat" t-on-change="captureChange"
|
||||
t-att-value="props.partner.vat || ''" />
|
||||
</div>
|
||||
<div t-if="pos.globalState.pricelists.length gt 1" class="partner-detail">
|
||||
<div t-if="pos.pricelists.length gt 1" class="partner-detail">
|
||||
<span class="label">Pricelist</span>
|
||||
<select class="detail" name="property_product_pricelist"
|
||||
t-on-change="captureChange">
|
||||
<t t-foreach="pos.globalState.pricelists" t-as="pricelist"
|
||||
<t t-foreach="pos.pricelists" t-as="pricelist"
|
||||
t-key="pricelist.id">
|
||||
<option t-att-value="pricelist.id"
|
||||
t-att-selected="props.partner.property_product_pricelist ? (pricelist.id === props.partner.property_product_pricelist[0] ? true : undefined) : pricelist.id === pos.globalState.default_pricelist.id ? true : undefined">
|
||||
t-att-selected="props.partner.property_product_pricelist ? (pricelist.id === props.partner.property_product_pricelist[0] ? true : undefined) : pricelist.id === pos.default_pricelist.id ? true : undefined">
|
||||
<t t-esc="pricelist.display_name" />
|
||||
</option>
|
||||
</t>
|
||||
|
||||
@@ -69,15 +69,15 @@ export class PartnerListScreen extends Component {
|
||||
// Getters
|
||||
|
||||
get currentOrder() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
|
||||
get partners() {
|
||||
let res;
|
||||
if (this.state.query && this.state.query.trim() !== "") {
|
||||
res = this.pos.globalState.db.search_partner(this.state.query.trim());
|
||||
res = this.pos.db.search_partner(this.state.query.trim());
|
||||
} else {
|
||||
res = this.pos.globalState.db.get_partners_sorted(1000);
|
||||
res = this.pos.db.get_partners_sorted(1000);
|
||||
}
|
||||
res.sort(function (a, b) {
|
||||
return (a.name || "").localeCompare(b.name || "");
|
||||
@@ -147,15 +147,14 @@ export class PartnerListScreen extends Component {
|
||||
}
|
||||
createPartner() {
|
||||
// initialize the edit screen with default details about country & state
|
||||
const { country_id, state_id } = this.pos.globalState.company;
|
||||
const { country_id, state_id } = this.pos.company;
|
||||
this.state.editModeProps.partner = { country_id, state_id };
|
||||
this.activateEditMode();
|
||||
}
|
||||
async saveChanges(processedChanges) {
|
||||
const { globalState } = this.pos;
|
||||
const partnerId = await this.orm.call("res.partner", "create_from_ui", [processedChanges]);
|
||||
await globalState.load_new_partners();
|
||||
this.state.selectedPartner = globalState.db.get_partner_by_id(partnerId);
|
||||
await this.pos.load_new_partners();
|
||||
this.state.selectedPartner = this.pos.db.get_partner_by_id(partnerId);
|
||||
this.confirm();
|
||||
}
|
||||
async searchPartner() {
|
||||
@@ -163,7 +162,7 @@ export class PartnerListScreen extends Component {
|
||||
this.state.currentOffset = 0;
|
||||
}
|
||||
const result = await this.getNewPartners();
|
||||
this.pos.globalState.addPartners(result);
|
||||
this.pos.addPartners(result);
|
||||
if (this.state.previousQuery == this.state.query) {
|
||||
this.state.currentOffset += result.length;
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@ export class PaymentScreenPaymentLines extends Component {
|
||||
title: this.env._t("New amount"),
|
||||
startingValue: parseFloat(paymentline.amount),
|
||||
isInputSelected: true,
|
||||
nbrDecimal: this.pos.globalState.currency.decimal_places,
|
||||
nbrDecimal: this.pos.currency.decimal_places,
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
|
||||
@@ -34,8 +34,8 @@ export class PaymentScreen extends Component {
|
||||
this.report = useService("report");
|
||||
this.notification = useService("pos_notification");
|
||||
this.hardwareProxy = useService("hardware_proxy");
|
||||
this.payment_methods_from_config = this.pos.globalState.payment_methods.filter((method) =>
|
||||
this.pos.globalState.config.payment_method_ids.includes(method.id)
|
||||
this.payment_methods_from_config = this.pos.payment_methods.filter((method) =>
|
||||
this.pos.config.payment_method_ids.includes(method.id)
|
||||
);
|
||||
this.numberBuffer = useService("number_buffer");
|
||||
this.numberBuffer.use(this._getNumberBufferConfig);
|
||||
@@ -62,7 +62,7 @@ export class PaymentScreen extends Component {
|
||||
return config;
|
||||
}
|
||||
get currentOrder() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
get paymentLines() {
|
||||
return this.currentOrder.get_paymentlines();
|
||||
@@ -158,8 +158,8 @@ export class PaymentScreen extends Component {
|
||||
title: tip ? this.env._t("Change Tip") : this.env._t("Add Tip"),
|
||||
startingValue: value,
|
||||
isInputSelected: true,
|
||||
nbrDecimal: this.pos.globalState.currency.decimal_places,
|
||||
inputSuffix: this.pos.globalState.currency.symbol,
|
||||
nbrDecimal: this.pos.currency.decimal_places,
|
||||
inputSuffix: this.pos.currency.symbol,
|
||||
});
|
||||
|
||||
if (confirmed) {
|
||||
@@ -203,8 +203,8 @@ export class PaymentScreen extends Component {
|
||||
}
|
||||
async validateOrder(isForceValidate) {
|
||||
this.numberBuffer.capture();
|
||||
if (this.pos.globalState.config.cash_rounding) {
|
||||
if (!this.pos.globalState.get_order().check_paymentlines_rounding()) {
|
||||
if (this.pos.config.cash_rounding) {
|
||||
if (!this.pos.get_order().check_paymentlines_rounding()) {
|
||||
this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Rounding error in payment lines"),
|
||||
body: this.env._t(
|
||||
@@ -225,7 +225,6 @@ export class PaymentScreen extends Component {
|
||||
}
|
||||
}
|
||||
async _finalizeValidation() {
|
||||
const { globalState } = this.pos;
|
||||
if (this.currentOrder.is_paid_with_cash() || this.currentOrder.get_change()) {
|
||||
this.hardwareProxy.openCashbox();
|
||||
}
|
||||
@@ -237,7 +236,7 @@ export class PaymentScreen extends Component {
|
||||
|
||||
try {
|
||||
// 1. Save order to server.
|
||||
syncOrderResult = await globalState.push_single_order(this.currentOrder);
|
||||
syncOrderResult = await this.pos.push_single_order(this.currentOrder);
|
||||
|
||||
// 2. Invoice.
|
||||
if (this.currentOrder.is_to_invoice()) {
|
||||
@@ -289,10 +288,10 @@ export class PaymentScreen extends Component {
|
||||
this.pos.showScreen(this.nextScreen);
|
||||
// Remove the order from the local storage so that when we refresh the page, the order
|
||||
// won't be there
|
||||
globalState.db.remove_unpaid_order(this.currentOrder);
|
||||
this.pos.db.remove_unpaid_order(this.currentOrder);
|
||||
|
||||
// Ask the user to sync the remaining unsynced orders.
|
||||
if (!hasError && syncOrderResult && globalState.db.get_orders().length) {
|
||||
if (!hasError && syncOrderResult && this.pos.db.get_orders().length) {
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Remaining unsynced orders"),
|
||||
body: this.env._t(
|
||||
@@ -303,7 +302,7 @@ export class PaymentScreen extends Component {
|
||||
// NOTE: Not yet sure if this should be awaited or not.
|
||||
// If awaited, some operations like changing screen
|
||||
// might not work.
|
||||
globalState.push_orders();
|
||||
this.pos.push_orders();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -410,7 +409,7 @@ export class PaymentScreen extends Component {
|
||||
this.currentOrder.get_rounding_applied()
|
||||
) > 0.00001
|
||||
) {
|
||||
if (!this.pos.globalState.payment_methods.some((pm) => pm.is_cash_count)) {
|
||||
if (!this.pos.payment_methods.some((pm) => pm.is_cash_count)) {
|
||||
this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Cannot return change without a cash payment method"),
|
||||
body: this.env._t(
|
||||
@@ -474,7 +473,7 @@ export class PaymentScreen extends Component {
|
||||
line.can_be_reversed = payment_terminal.supports_reversals;
|
||||
// Automatically validate the order when after an electronic payment,
|
||||
// the current order is fully paid and due is zero.
|
||||
const { config, currency } = this.pos.globalState;
|
||||
const { config, currency } = this.pos;
|
||||
if (
|
||||
this.currentOrder.is_paid() &&
|
||||
floatIsZero(this.currentOrder.get_due(), currency.decimal_places) &&
|
||||
|
||||
@@ -86,16 +86,16 @@
|
||||
t-on-click="toggleIsToInvoice">
|
||||
<i class="fa fa-file-text-o" /> Invoice
|
||||
</div>
|
||||
<div t-if="pos.globalState.config.iface_tipproduct and pos.globalState.config.tip_product_id" class="button js_tip"
|
||||
<div t-if="pos.config.iface_tipproduct and pos.config.tip_product_id" class="button js_tip"
|
||||
t-att-class="{ highlight: currentOrder.get_tip() }"
|
||||
t-on-click="addTip">
|
||||
<i class="fa fa-heart" /> Tip <t t-if="currentOrder.get_tip() != 0">(<t t-esc="env.utils.formatCurrency(currentOrder.get_tip())"/>)</t>
|
||||
</div>
|
||||
<div t-if="pos.globalState.config.iface_cashdrawer" class="button js_cashdrawer"
|
||||
<div t-if="pos.config.iface_cashdrawer" class="button js_cashdrawer"
|
||||
t-on-click="openCashbox">
|
||||
<i class="fa fa-archive" /> Open Cashbox
|
||||
</div>
|
||||
<div t-if="pos.globalState.config.ship_later" class="button"
|
||||
<div t-if="pos.config.ship_later" class="button"
|
||||
t-att-class="{ highlight: currentOrder.getShippingDate() }"
|
||||
t-on-click="toggleShippingDatePicker">
|
||||
<i class="fa fa-clock-o" /> Ship Later
|
||||
|
||||
@@ -22,6 +22,6 @@ export class ActionpadWidget extends Component {
|
||||
return this.props.partner && this.props.partner.name.length > 10;
|
||||
}
|
||||
get highlightPay() {
|
||||
return this.pos.globalState.get_order()?.orderlines?.length;
|
||||
return this.pos.get_order()?.orderlines?.length;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
Customer
|
||||
</t>
|
||||
</button>
|
||||
<button class="button pay validation pay-order-button" t-on-click="props.actionToTrigger ? this.props.actionToTrigger : () => pos.globalState.get_order().pay()">
|
||||
<button class="button pay validation pay-order-button" t-on-click="props.actionToTrigger ? this.props.actionToTrigger : () => pos.get_order().pay()">
|
||||
<div class="pay-circle" t-att-class="{ 'highlight': this.highlightPay }">
|
||||
<i class="oi oi-chevron-right" role="img" aria-label="Pay" title="Pay" />
|
||||
</div>
|
||||
|
||||
+2
-2
@@ -12,7 +12,7 @@ export class CustomerButton extends Component {
|
||||
}
|
||||
|
||||
get partner() {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
return order ? order.get_partner() : null;
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,6 @@ ProductScreen.addControlButton({
|
||||
component: CustomerButton,
|
||||
position: ["before", "SetFiscalPositionButton"],
|
||||
condition: function () {
|
||||
return this.pos.globalState.config.module_pos_restaurant;
|
||||
return this.pos.config.module_pos_restaurant;
|
||||
},
|
||||
});
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ export class OrderlineCustomerNoteButton extends Component {
|
||||
this.popup = useService("popup");
|
||||
}
|
||||
async onClick() {
|
||||
const selectedOrderline = this.pos.globalState.get_order().get_selected_orderline();
|
||||
const selectedOrderline = this.pos.get_order().get_selected_orderline();
|
||||
// FIXME POSREF can this happen? Shouldn't the orderline just be a prop?
|
||||
if (!selectedOrderline) {
|
||||
return;
|
||||
|
||||
+3
-3
@@ -14,7 +14,7 @@ export class SetFiscalPositionButton extends Component {
|
||||
this.popup = useService("popup");
|
||||
}
|
||||
get currentOrder() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
get currentFiscalPositionName() {
|
||||
return this.currentOrder && this.currentOrder.fiscal_position
|
||||
@@ -30,7 +30,7 @@ export class SetFiscalPositionButton extends Component {
|
||||
isSelected: !currentFiscalPosition,
|
||||
},
|
||||
];
|
||||
for (const fiscalPos of this.pos.globalState.fiscal_positions) {
|
||||
for (const fiscalPos of this.pos.fiscal_positions) {
|
||||
fiscalPosList.push({
|
||||
id: fiscalPos.id,
|
||||
label: fiscalPos.name,
|
||||
@@ -61,7 +61,7 @@ export class SetFiscalPositionButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: SetFiscalPositionButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.fiscal_positions.length > 0;
|
||||
return this.pos.fiscal_positions.length > 0;
|
||||
},
|
||||
position: ["before", "SetPricelistButton"],
|
||||
});
|
||||
|
||||
+4
-4
@@ -14,7 +14,7 @@ export class SetPricelistButton extends Component {
|
||||
this.popup = useService("popup");
|
||||
}
|
||||
get currentOrder() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
get currentPricelistName() {
|
||||
const order = this.currentOrder;
|
||||
@@ -24,7 +24,7 @@ export class SetPricelistButton extends Component {
|
||||
// Create the list to be passed to the SelectionPopup.
|
||||
// Pricelist object is passed as item in the list because it
|
||||
// is the object that will be returned when the popup is confirmed.
|
||||
const selectionList = this.pos.globalState.pricelists.map((pricelist) => ({
|
||||
const selectionList = this.pos.pricelists.map((pricelist) => ({
|
||||
id: pricelist.id,
|
||||
label: pricelist.name,
|
||||
isSelected:
|
||||
@@ -32,7 +32,7 @@ export class SetPricelistButton extends Component {
|
||||
item: pricelist,
|
||||
}));
|
||||
|
||||
if (!this.pos.globalState.default_pricelist) {
|
||||
if (!this.pos.default_pricelist) {
|
||||
selectionList.push({
|
||||
id: null,
|
||||
label: this.env._t("Default Price"),
|
||||
@@ -55,7 +55,7 @@ export class SetPricelistButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: SetPricelistButton,
|
||||
condition: function () {
|
||||
const { config, pricelists } = this.pos.globalState;
|
||||
const { config, pricelists } = this.pos;
|
||||
return config.use_pricelist && pricelists.length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
+2
-2
@@ -15,11 +15,11 @@ export class ProductInfoButton extends Component {
|
||||
this.pos = usePos();
|
||||
}
|
||||
async click() {
|
||||
const orderline = this.pos.globalState.get_order().get_selected_orderline();
|
||||
const orderline = this.pos.get_order().get_selected_orderline();
|
||||
if (orderline) {
|
||||
const product = orderline.get_product();
|
||||
const quantity = orderline.get_quantity();
|
||||
const info = await this.pos.globalState.getProductInfo(product, quantity);
|
||||
const info = await this.pos.getProductInfo(product, quantity);
|
||||
this.popup.add(ProductInfoPopup, { info: info, product: product });
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ export class RefundButton extends Component {
|
||||
this.pos = usePos();
|
||||
}
|
||||
click() {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
const partner = order.get_partner();
|
||||
const searchDetails = partner ? { fieldName: "PARTNER", searchTerm: partner.name } : {};
|
||||
this.pos.showScreen("TicketScreen", {
|
||||
|
||||
+6
-7
@@ -13,7 +13,7 @@ export class SaveButton extends Component {
|
||||
this.notification = useService("pos_notification");
|
||||
}
|
||||
onClick() {
|
||||
const orderline = this.pos.globalState.get_order().get_selected_orderline();
|
||||
const orderline = this.pos.get_order().get_selected_orderline();
|
||||
if (!orderline) {
|
||||
this.notification.add(this.env._t("You cannot save an empty order"), 3000);
|
||||
return;
|
||||
@@ -22,14 +22,13 @@ export class SaveButton extends Component {
|
||||
this.notification.add(this.env._t("Order saved for later"), 3000);
|
||||
}
|
||||
_selectEmptyOrder() {
|
||||
const { globalState } = this.pos;
|
||||
const orders = globalState.get_order_list();
|
||||
const orders = this.pos.get_order_list();
|
||||
const emptyOrders = orders.filter((order) => order.is_empty());
|
||||
if (emptyOrders.length > 0) {
|
||||
globalState.sendDraftToServer();
|
||||
globalState.set_order(emptyOrders[0]);
|
||||
this.pos.sendDraftToServer();
|
||||
this.pos.set_order(emptyOrders[0]);
|
||||
} else {
|
||||
globalState.add_new_order();
|
||||
this.pos.add_new_order();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +36,6 @@ export class SaveButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: SaveButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.config.trusted_config_ids.length > 0;
|
||||
return this.pos.config.trusted_config_ids.length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -22,13 +22,13 @@ export class NumpadWidget extends Component {
|
||||
}
|
||||
get hasPriceControlRights() {
|
||||
return (
|
||||
this.pos.globalState.cashierHasPriceControlRights() &&
|
||||
this.pos.cashierHasPriceControlRights() &&
|
||||
!this.props.disabledModes.includes("price")
|
||||
);
|
||||
}
|
||||
get hasManualDiscount() {
|
||||
return (
|
||||
this.pos.globalState.config.manual_discount &&
|
||||
this.pos.config.manual_discount &&
|
||||
!this.props.disabledModes.includes("discount")
|
||||
);
|
||||
}
|
||||
@@ -41,7 +41,7 @@ export class NumpadWidget extends Component {
|
||||
}
|
||||
this.numberBuffer.capture();
|
||||
this.numberBuffer.reset();
|
||||
this.pos.globalState.numpadMode = mode;
|
||||
this.pos.numpadMode = mode;
|
||||
}
|
||||
sendInput(key) {
|
||||
this.numberBuffer.sendKey(key);
|
||||
|
||||
@@ -30,7 +30,7 @@ export class OrderWidget extends Component {
|
||||
);
|
||||
}
|
||||
get order() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
get orderlinesArray() {
|
||||
return this.order ? this.order.get_orderlines() : [];
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ export class OrderSummary extends Component {
|
||||
const totalWithoutTax = this.props.order.get_total_without_tax();
|
||||
const taxAmount = total - totalWithoutTax;
|
||||
return {
|
||||
hasTax: !floatIsZero(taxAmount, this.pos.globalState.currency.decimal_places),
|
||||
hasTax: !floatIsZero(taxAmount, this.pos.currency.decimal_places),
|
||||
displayAmount: this.env.utils.formatCurrency(taxAmount),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ export class Orderline extends Component {
|
||||
}
|
||||
selectLine() {
|
||||
const line = this.props.line; // the orderline
|
||||
if (this.pos.globalState.get_order().selected_orderline.id !== line.id) {
|
||||
if (this.pos.get_order().selected_orderline.id !== line.id) {
|
||||
this.mp_dbclk_time = new Date().getTime();
|
||||
} else if (!this.mp_dbclk_time) {
|
||||
this.mp_dbclk_time = new Date().getTime();
|
||||
@@ -37,9 +37,9 @@ export class Orderline extends Component {
|
||||
return {
|
||||
selected: this.props.line.selected,
|
||||
"has-change":
|
||||
this.props.line.hasChange && this.pos.globalState.config.module_pos_restaurant,
|
||||
this.props.line.hasChange && this.pos.config.module_pos_restaurant,
|
||||
"skip-change":
|
||||
this.props.line.skipChange && this.pos.globalState.config.module_pos_restaurant,
|
||||
this.props.line.skipChange && this.pos.config.module_pos_restaurant,
|
||||
};
|
||||
}
|
||||
get customerNote() {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<span class="product-name">
|
||||
<t t-esc="props.line.get_full_product_name()"/>
|
||||
<span> </span>
|
||||
<t t-if="props.line.get_product().tracking!=='none' && (pos.globalState.picking_type.use_create_lots || pos.globalState.picking_type.use_existing_lots)">
|
||||
<t t-if="props.line.get_product().tracking!=='none' && (pos.picking_type.use_create_lots || pos.picking_type.use_existing_lots)">
|
||||
<t t-if="props.line.has_valid_product_lot()">
|
||||
<i t-on-click.stop="lotIconClicked"
|
||||
class="oe_link_icon fa fa-list oe_icon line-lot-icon oe_green"
|
||||
|
||||
@@ -25,11 +25,11 @@ export class ProductItem extends Component {
|
||||
return `/web/image?model=product.product&field=image_128&id=${product.id}&unique=${product.write_date}`;
|
||||
}
|
||||
get pricelist() {
|
||||
const current_order = this.pos.globalState.get_order();
|
||||
const current_order = this.pos.get_order();
|
||||
if (current_order) {
|
||||
return current_order.pricelist;
|
||||
}
|
||||
return this.pos.globalState.default_pricelist;
|
||||
return this.pos.default_pricelist;
|
||||
}
|
||||
get price() {
|
||||
const formattedUnitPrice = this.env.utils.formatCurrency(
|
||||
@@ -37,7 +37,7 @@ export class ProductItem extends Component {
|
||||
);
|
||||
if (this.props.product.to_weight) {
|
||||
return `${formattedUnitPrice}/${
|
||||
this.pos.globalState.units_by_id[this.props.product.uom_id[0]].name
|
||||
this.pos.units_by_id[this.props.product.uom_id[0]].name
|
||||
}`;
|
||||
} else {
|
||||
return formattedUnitPrice;
|
||||
|
||||
+4
-4
@@ -19,14 +19,14 @@ export class ProductInfoPopup extends AbstractAwaitablePopup {
|
||||
Object.assign(this, this.props.info);
|
||||
}
|
||||
searchProduct(productName) {
|
||||
this.pos.globalState.setSelectedCategoryId(0);
|
||||
this.pos.globalState.searchProductWord = productName;
|
||||
this.pos.setSelectedCategoryId(0);
|
||||
this.pos.searchProductWord = productName;
|
||||
this.cancel();
|
||||
}
|
||||
_hasMarginsCostsAccessRights() {
|
||||
const isAccessibleToEveryUser =
|
||||
this.pos.globalState.config.is_margins_costs_accessible_to_every_user;
|
||||
const isCashierManager = this.pos.globalState.get_cashier().role === "manager";
|
||||
this.pos.config.is_margins_costs_accessible_to_every_user;
|
||||
const isCashierManager = this.pos.get_cashier().role === "manager";
|
||||
return isAccessibleToEveryUser || isCashierManager;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -50,7 +50,7 @@
|
||||
</div>
|
||||
<div class="section-inventory" t-if="productInfo.warehouses.length > 0">
|
||||
<div class="section-title">
|
||||
<span>Inventory <t t-if="pos.globalState.pos_session.update_stock_at_closing">(as of opening)</t></span>
|
||||
<span>Inventory <t t-if="pos.pos_session.update_stock_at_closing">(as of opening)</t></span>
|
||||
<div class="section-title-line"></div>
|
||||
</div>
|
||||
<div class="section-inventory-body">
|
||||
|
||||
+5
-5
@@ -42,26 +42,26 @@ export class ProductsWidgetControlPanel extends Component {
|
||||
this.state.mobileSearchBarIsShown = !this.state.mobileSearchBarIsShown;
|
||||
}
|
||||
_clearSearch() {
|
||||
this.pos.globalState.searchProductWord = "";
|
||||
this.pos.searchProductWord = "";
|
||||
this.props.clearSearch();
|
||||
}
|
||||
get displayCategImages() {
|
||||
return (
|
||||
!this.ui.isSmall &&
|
||||
Object.values(this.pos.globalState.db.category_by_id).some((categ) => categ.has_image)
|
||||
Object.values(this.pos.db.category_by_id).some((categ) => categ.has_image)
|
||||
);
|
||||
}
|
||||
updateSearch(event) {
|
||||
this.props.updateSearch(this.pos.globalState.searchProductWord);
|
||||
this.props.updateSearch(this.pos.searchProductWord);
|
||||
}
|
||||
async _onPressEnterKey() {
|
||||
if (!this.pos.globalState.searchProductWord) {
|
||||
if (!this.pos.searchProductWord) {
|
||||
return;
|
||||
}
|
||||
this.props.loadProductFromServer();
|
||||
}
|
||||
searchProductFromInfo(productName) {
|
||||
this.pos.globalState.searchProductWord = productName;
|
||||
this.pos.searchProductWord = productName;
|
||||
this.props.switchCategory(0);
|
||||
this.props.updateSearch(productName);
|
||||
}
|
||||
|
||||
+2
-2
@@ -11,8 +11,8 @@
|
||||
<t t-if="!state.isMobile || state.mobileSearchBarIsShown">
|
||||
<div class="pos-search-bar">
|
||||
<i class="fa fa-search"/>
|
||||
<input t-model="this.pos.globalState.searchProductWord" placeholder="Search Products..." type="text" autofocus="autofocus" t-on-keyup="updateSearch" />
|
||||
<i t-if="this.pos.globalState.searchProductWord" class="fa fa-times" t-on-click="_clearSearch"/>
|
||||
<input t-model="this.pos.searchProductWord" placeholder="Search Products..." type="text" autofocus="autofocus" t-on-keyup="updateSearch" />
|
||||
<i t-if="this.pos.searchProductWord" class="fa fa-times" t-on-click="_clearSearch"/>
|
||||
</div>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
+16
-16
@@ -31,16 +31,16 @@ export class ProductsWidget extends Component {
|
||||
this.orm = useService("orm");
|
||||
}
|
||||
get hasProducts() {
|
||||
return Object.keys(this.pos.globalState.db.product_by_id).length > 0;
|
||||
return Object.keys(this.pos.db.product_by_id).length > 0;
|
||||
}
|
||||
get selectedCategoryId() {
|
||||
return this.pos.globalState.selectedCategoryId;
|
||||
return this.pos.selectedCategoryId;
|
||||
}
|
||||
get searchWord() {
|
||||
return this.pos.globalState.searchProductWord.trim();
|
||||
return this.pos.searchProductWord.trim();
|
||||
}
|
||||
get productsToDisplay() {
|
||||
const { db } = this.pos.globalState;
|
||||
const { db } = this.pos;
|
||||
let list = [];
|
||||
if (this.searchWord !== "") {
|
||||
list = db.search_product_in_category(this.selectedCategoryId, this.searchWord);
|
||||
@@ -52,13 +52,13 @@ export class ProductsWidget extends Component {
|
||||
});
|
||||
}
|
||||
get subcategories() {
|
||||
const { db } = this.pos.globalState;
|
||||
const { db } = this.pos;
|
||||
return db
|
||||
.get_category_childs_ids(this.selectedCategoryId)
|
||||
.map((id) => db.get_category_by_id(id));
|
||||
}
|
||||
get breadcrumbs() {
|
||||
const { db } = this.pos.globalState;
|
||||
const { db } = this.pos;
|
||||
if (this.selectedCategoryId === db.root_category_id) {
|
||||
return [];
|
||||
}
|
||||
@@ -68,25 +68,25 @@ export class ProductsWidget extends Component {
|
||||
].map((id) => db.get_category_by_id(id));
|
||||
}
|
||||
get hasNoCategories() {
|
||||
return this.pos.globalState.db.get_category_childs_ids(0).length === 0;
|
||||
return this.pos.db.get_category_childs_ids(0).length === 0;
|
||||
}
|
||||
get shouldShowButton() {
|
||||
return this.productsToDisplay.length === 0 && this.searchWord;
|
||||
}
|
||||
switchCategory(categoryId) {
|
||||
this.pos.globalState.setSelectedCategoryId(categoryId);
|
||||
this.pos.setSelectedCategoryId(categoryId);
|
||||
}
|
||||
updateSearch(searchWord) {
|
||||
this.pos.globalState.searchProductWord = searchWord;
|
||||
this.pos.searchProductWord = searchWord;
|
||||
}
|
||||
clearSearch() {
|
||||
this.pos.globalState.searchProductWord = "";
|
||||
this.pos.searchProductWord = "";
|
||||
}
|
||||
updateProductList(event) {
|
||||
this.switchCategory(0);
|
||||
}
|
||||
async onPressEnterKey() {
|
||||
const { searchProductWord } = this.pos.globalState;
|
||||
const { searchProductWord } = this.pos;
|
||||
if (!searchProductWord) {
|
||||
return;
|
||||
}
|
||||
@@ -117,7 +117,7 @@ export class ProductsWidget extends Component {
|
||||
}
|
||||
}
|
||||
async loadProductFromDB() {
|
||||
const { searchProductWord } = this.pos.globalState;
|
||||
const { searchProductWord } = this.pos;
|
||||
if (!searchProductWord) {
|
||||
return;
|
||||
}
|
||||
@@ -144,7 +144,7 @@ export class ProductsWidget extends Component {
|
||||
}
|
||||
);
|
||||
if (ProductIds.length) {
|
||||
await this.pos.globalState._addProducts(ProductIds, false);
|
||||
await this.pos._addProducts(ProductIds, false);
|
||||
}
|
||||
this.updateProductList();
|
||||
return ProductIds;
|
||||
@@ -169,10 +169,10 @@ export class ProductsWidget extends Component {
|
||||
const { products, categories } = await this.orm.call(
|
||||
"pos.session",
|
||||
"load_product_frontend",
|
||||
[this.pos.globalState.pos_session.id]
|
||||
[this.pos.pos_session.id]
|
||||
);
|
||||
this.pos.globalState.db.add_categories(categories);
|
||||
this.pos.globalState._loadProductProduct(products);
|
||||
this.pos.db.add_categories(categories);
|
||||
this.pos._loadProductProduct(products);
|
||||
}
|
||||
|
||||
createNewProducts() {
|
||||
|
||||
@@ -72,7 +72,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
return this.currentOrder ? this.currentOrder.get_partner() : null;
|
||||
}
|
||||
get currentOrder() {
|
||||
return this.pos.globalState.get_order();
|
||||
return this.pos.get_order();
|
||||
}
|
||||
get total() {
|
||||
return this.env.utils.formatCurrency(this.currentOrder?.get_total_with_tax() ?? 0);
|
||||
@@ -81,16 +81,15 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
return this.currentOrder.orderlines?.reduce((items, line) => items + line.quantity, 0) ?? 0;
|
||||
}
|
||||
async updateSelectedOrderline({ buffer, key }) {
|
||||
const { globalState } = this.pos;
|
||||
if (globalState.numpadMode === "quantity" && globalState.disallowLineQuantityChange()) {
|
||||
const order = globalState.get_order();
|
||||
if (this.pos.numpadMode === "quantity" && this.pos.disallowLineQuantityChange()) {
|
||||
const order = this.pos.get_order();
|
||||
if (!order.orderlines.length) {
|
||||
return;
|
||||
}
|
||||
const selectedLine = order.get_selected_orderline();
|
||||
const orderlines = order.orderlines;
|
||||
const lastId = orderlines.length !== 0 && orderlines.at(orderlines.length - 1).cid;
|
||||
const currentQuantity = globalState.get_order().get_selected_orderline().get_quantity();
|
||||
const currentQuantity = this.pos.get_order().get_selected_orderline().get_quantity();
|
||||
|
||||
if (selectedLine.noDecrease) {
|
||||
this.popup.add(ErrorPopup, {
|
||||
@@ -112,12 +111,12 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
this._setValue(val);
|
||||
if (val == "remove") {
|
||||
this.numberBuffer.reset();
|
||||
globalState.numpadMode = "quantity";
|
||||
this.pos.numpadMode = "quantity";
|
||||
}
|
||||
}
|
||||
}
|
||||
_setValue(val) {
|
||||
const { numpadMode } = this.pos.globalState;
|
||||
const { numpadMode } = this.pos;
|
||||
if (this.currentOrder.get_selected_orderline()) {
|
||||
if (numpadMode === "quantity") {
|
||||
const result = this.currentOrder.get_selected_orderline().set_quantity(val);
|
||||
@@ -134,8 +133,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
}
|
||||
}
|
||||
async _barcodeProductAction(code) {
|
||||
const { globalState } = this.pos;
|
||||
let product = globalState.db.get_product_by_barcode(code.base_code);
|
||||
let product = this.pos.db.get_product_by_barcode(code.base_code);
|
||||
if (!product) {
|
||||
// find the barcode in the backend
|
||||
let foundProductIds = [];
|
||||
@@ -143,9 +141,9 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
["barcode", "=", code.base_code],
|
||||
]);
|
||||
if (foundProductIds.length) {
|
||||
await globalState._addProducts(foundProductIds);
|
||||
await this.pos._addProducts(foundProductIds);
|
||||
// assume that the result is unique.
|
||||
product = globalState.db.get_product_by_id(foundProductIds[0]);
|
||||
product = this.pos.db.get_product_by_id(foundProductIds[0]);
|
||||
} else {
|
||||
return this.popup.add(ErrorBarcodePopup, { code: code.base_code });
|
||||
}
|
||||
@@ -180,7 +178,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
this.numberBuffer.reset();
|
||||
}
|
||||
_barcodePartnerAction(code) {
|
||||
const partner = this.pos.globalState.db.get_partner_by_barcode(code.code);
|
||||
const partner = this.pos.db.get_partner_by_barcode(code.code);
|
||||
if (partner) {
|
||||
if (this.currentOrder.get_partner() !== partner) {
|
||||
this.currentOrder.set_partner(partner);
|
||||
@@ -209,7 +207,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
});
|
||||
const newQuantity = inputNumber && inputNumber !== "" ? parseFloat(inputNumber) : null;
|
||||
if (confirmed && newQuantity !== null) {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
const selectedLine = order.get_selected_orderline();
|
||||
const currentQuantity = selectedLine.get_quantity();
|
||||
if (newQuantity >= currentQuantity) {
|
||||
@@ -268,23 +266,22 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
// FIXME POSREF this is dead code, check if we need the business logic that's left in here
|
||||
// If we do it should be in the model.
|
||||
async onClickPay() {
|
||||
const { globalState } = this.pos;
|
||||
if (globalState.get_order().server_id) {
|
||||
if (this.pos.get_order().server_id) {
|
||||
try {
|
||||
const isPaid = await this.orm.call("pos.order", "is_already_paid", [
|
||||
globalState.get_order().server_id,
|
||||
this.pos.get_order().server_id,
|
||||
]);
|
||||
if (isPaid) {
|
||||
const searchDetails = {
|
||||
fieldName: "RECEIPT_NUMBER",
|
||||
searchTerm: globalState.get_order().uid,
|
||||
searchTerm: this.pos.get_order().uid,
|
||||
};
|
||||
this.pos.showScreen("TicketScreen", {
|
||||
ui: { filter: "SYNCED", searchDetails },
|
||||
});
|
||||
this.notification.add(this.env._t("The order has been already paid."), 3000);
|
||||
globalState.removeOrder(globalState.get_order(), false);
|
||||
globalState.add_new_order();
|
||||
this.pos.removeOrder(this.pos.get_order(), false);
|
||||
this.pos.add_new_order();
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
@@ -298,7 +295,7 @@ export class ProductScreen extends ControlButtonsMixin(Component) {
|
||||
this.currentOrder.pay();
|
||||
}
|
||||
switchPane() {
|
||||
this.pos.globalState.switchPane();
|
||||
this.pos.switchPane();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<t t-name="point_of_sale.ProductScreen" owl="1">
|
||||
<div class="product-screen screen" t-att-class="{ oe_hidden: !props.isShown }">
|
||||
<div class="screen-full-width">
|
||||
<div class="leftpane pane-border" t-if="!ui.isSmall || pos.globalState.mobile_pane === 'left'">
|
||||
<div class="leftpane pane-border" t-if="!ui.isSmall || pos.mobile_pane === 'left'">
|
||||
<OrderWidget/>
|
||||
<div class="pads">
|
||||
<div class="control-buttons">
|
||||
@@ -22,11 +22,11 @@
|
||||
onClickMore.bind="displayAllControlPopup" />
|
||||
<NumpadWidget
|
||||
updateSelectedOrderline.bind="updateSelectedOrderline"
|
||||
activeMode="pos.globalState.numpadMode" />
|
||||
activeMode="pos.numpadMode" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="rightpane" t-if="!ui.isSmall || pos.globalState.mobile_pane === 'right'">
|
||||
<div class="rightpane" t-if="!ui.isSmall || pos.mobile_pane === 'right'">
|
||||
<ProductsWidget />
|
||||
<t t-if="ui.isSmall">
|
||||
<div class="product-reminder" t-if="showProductReminder" t-key="animationKey" t-ref="reminder">
|
||||
|
||||
@@ -197,7 +197,7 @@
|
||||
</t>
|
||||
<t t-elif="line.discount !== 0">
|
||||
<div class="pos-receipt-left-padding">
|
||||
<t t-if="pos.globalState.config.iface_tax_included === 'total'">
|
||||
<t t-if="pos.config.iface_tax_included === 'total'">
|
||||
<t t-esc="env.utils.formatCurrency(line.price_with_tax_before_discount, false)"/>
|
||||
</t>
|
||||
<t t-else="">
|
||||
@@ -211,7 +211,7 @@
|
||||
</div>
|
||||
</t>
|
||||
<div class="pos-receipt-left-padding">
|
||||
<t t-esc="Math.round(line.quantity * Math.pow(10, pos.globalState.dp['Product Unit of Measure'])) / Math.pow(10, pos.globalState.dp['Product Unit of Measure'])"/>
|
||||
<t t-esc="Math.round(line.quantity * Math.pow(10, pos.dp['Product Unit of Measure'])) / Math.pow(10, pos.dp['Product Unit of Measure'])"/>
|
||||
<t t-if="!line.is_in_unit" t-esc="line.unit_name" />
|
||||
x
|
||||
<t t-esc="env.utils.formatCurrency(line.price_display_one)" />
|
||||
|
||||
@@ -23,7 +23,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
this.orderReceipt = useRef("order-receipt");
|
||||
this.buttonMailReceipt = useRef("order-mail-receipt-button");
|
||||
this.buttonPrintReceipt = useRef("order-print-receipt-button");
|
||||
this.currentOrder = this.pos.globalState.get_order();
|
||||
this.currentOrder = this.pos.get_order();
|
||||
const partner = this.currentOrder.get_partner();
|
||||
this.orderUiState = this.currentOrder.uiState.ReceiptScreen;
|
||||
this.orderUiState.inputEmail =
|
||||
@@ -49,14 +49,14 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
onWillStart(async () => {
|
||||
// When the order is paid, if there is still a part of the order
|
||||
// to send in preparation it is automatically sent
|
||||
if (this.pos.globalState.orderPreparationCategories.size) {
|
||||
if (this.pos.orderPreparationCategories.size) {
|
||||
await this.pos.sendOrderInPreparation(this.currentOrder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_addNewOrder() {
|
||||
this.pos.globalState.add_new_order();
|
||||
this.pos.add_new_order();
|
||||
}
|
||||
onSendEmail() {
|
||||
if (this.buttonMailReceipt.el.classList.contains("fa-spin")) {
|
||||
@@ -96,7 +96,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
get orderAmountPlusTip() {
|
||||
const order = this.currentOrder;
|
||||
const orderTotalAmount = order.get_total_with_tax();
|
||||
const tip_product_id = this.pos.globalState.config.tip_product_id?.[0];
|
||||
const tip_product_id = this.pos.config.tip_product_id?.[0];
|
||||
const tipLine = order
|
||||
.get_orderlines()
|
||||
.find((line) => tip_product_id && line.product.id === tip_product_id);
|
||||
@@ -137,24 +137,24 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
}
|
||||
}
|
||||
orderDone() {
|
||||
this.pos.globalState.removeOrder(this.currentOrder);
|
||||
this.pos.removeOrder(this.currentOrder);
|
||||
this._addNewOrder();
|
||||
const { name, props } = this.nextScreen;
|
||||
this.pos.showScreen(name, props);
|
||||
}
|
||||
resumeOrder() {
|
||||
this.pos.globalState.removeOrder(this.currentOrder);
|
||||
this.pos.globalState.selectNextOrder();
|
||||
this.pos.removeOrder(this.currentOrder);
|
||||
this.pos.selectNextOrder();
|
||||
const { name, props } = this.ticketScreen;
|
||||
this.pos.showScreen(name, props);
|
||||
}
|
||||
continueSplitting() {
|
||||
this.pos.globalState.selectedOrder = this.currentOrder.originalSplittedOrder;
|
||||
this.pos.globalState.removeOrder(this.currentOrder);
|
||||
this.pos.selectedOrder = this.currentOrder.originalSplittedOrder;
|
||||
this.pos.removeOrder(this.currentOrder);
|
||||
this.pos.showScreen("ProductScreen");
|
||||
}
|
||||
isResumeVisible() {
|
||||
return this.pos.globalState.get_order_list().length > 1;
|
||||
return this.pos.get_order_list().length > 1;
|
||||
}
|
||||
async printReceipt() {
|
||||
this.buttonPrintReceipt.el.className = "fa fa-fw fa-spin fa-circle-o-notch";
|
||||
@@ -170,7 +170,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
}
|
||||
}
|
||||
_shouldAutoPrint() {
|
||||
return this.pos.globalState.config.iface_print_auto && !this.currentOrder._printed;
|
||||
return this.pos.config.iface_print_auto && !this.currentOrder._printed;
|
||||
}
|
||||
_shouldCloseImmediately() {
|
||||
var invoiced_finalized = this.currentOrder.is_to_invoice()
|
||||
@@ -178,7 +178,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
: true;
|
||||
return (
|
||||
this.hardwareProxy.printer &&
|
||||
this.pos.globalState.config.iface_print_skip_screen &&
|
||||
this.pos.config.iface_print_skip_screen &&
|
||||
invoiced_finalized
|
||||
);
|
||||
}
|
||||
@@ -193,7 +193,7 @@ export class ReceiptScreen extends AbstractReceiptScreen {
|
||||
email: this.orderUiState.inputEmail,
|
||||
name: partner ? partner.name : this.orderUiState.inputEmail,
|
||||
};
|
||||
const order_server_id = this.pos.globalState.validated_orders_name_server_id_map[orderName];
|
||||
const order_server_id = this.pos.validated_orders_name_server_id_map[orderName];
|
||||
if (!order_server_id) {
|
||||
this.popup.add(OfflineErrorPopup, {
|
||||
title: this.env._t("Unsynced order"),
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ export class ReprintReceiptScreen extends AbstractReceiptScreen {
|
||||
this.pos.showScreen("TicketScreen", { reuseSavedUIState: true });
|
||||
}
|
||||
async printReceipt() {
|
||||
const { iface_print_skip_screen } = this.pos.globalState.config;
|
||||
const { iface_print_skip_screen } = this.pos.config;
|
||||
if (this.hardwareProxy.printer && iface_print_skip_screen) {
|
||||
const result = await this._printReceipt();
|
||||
if (result) {
|
||||
|
||||
@@ -60,8 +60,8 @@ export class ScaleScreen extends Component {
|
||||
setTimeout(() => this._setWeight(), 500);
|
||||
}
|
||||
get _activePricelist() {
|
||||
const current_order = this.pos.globalState.get_order();
|
||||
let current_pricelist = this.pos.globalState.default_pricelist;
|
||||
const current_order = this.pos.get_order();
|
||||
let current_pricelist = this.pos.default_pricelist;
|
||||
if (current_order) {
|
||||
current_pricelist = current_order.pricelist;
|
||||
}
|
||||
@@ -76,7 +76,7 @@ export class ScaleScreen extends Component {
|
||||
if (!unit_id) {
|
||||
return defaultstr;
|
||||
}
|
||||
const unit = this.pos.globalState.units_by_id[unit_id[0]];
|
||||
const unit = this.pos.units_by_id[unit_id[0]];
|
||||
const weight = round_pr(this.state.weight || 0, unit.rounding);
|
||||
let weightstr = weight.toFixed(Math.ceil(Math.log(1.0 / unit.rounding) / Math.log(10)));
|
||||
weightstr += " " + unit.name;
|
||||
@@ -96,7 +96,7 @@ export class ScaleScreen extends Component {
|
||||
if (!this.props.product) {
|
||||
return "";
|
||||
}
|
||||
return this.pos.globalState.units_by_id[this.props.product.uom_id[0]].name;
|
||||
return this.pos.units_by_id[this.props.product.uom_id[0]].name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-4
@@ -20,7 +20,7 @@ export class OrderlineDetails extends Component {
|
||||
const formatQty = (line) => {
|
||||
const quantity = line.get_quantity();
|
||||
const unit = line.get_unit();
|
||||
const decimals = this.pos.globalState.dp["Product Unit of Measure"];
|
||||
const decimals = this.pos.dp["Product Unit of Measure"];
|
||||
const rounding = Math.max(unit.rounding, Math.pow(10, -decimals));
|
||||
const roundedQuantity = round_pr(quantity, rounding);
|
||||
return formatFloat(roundedQuantity, { digits: [69, decimals] });
|
||||
@@ -55,17 +55,17 @@ export class OrderlineDetails extends Component {
|
||||
return this.props.line.get_customer_note();
|
||||
}
|
||||
getToRefundDetail() {
|
||||
return this.pos.globalState.toRefundLines[this.props.line.id];
|
||||
return this.pos.toRefundLines[this.props.line.id];
|
||||
}
|
||||
hasRefundedQty() {
|
||||
return !this.pos.globalState.isProductQtyZero(this.props.line.refunded_qty);
|
||||
return !this.pos.isProductQtyZero(this.props.line.refunded_qty);
|
||||
}
|
||||
getFormattedRefundedQty() {
|
||||
return this.env.utils.formatProductQty(this.props.line.refunded_qty);
|
||||
}
|
||||
hasToRefundQty() {
|
||||
const toRefundDetail = this.getToRefundDetail();
|
||||
return !this.pos.globalState.isProductQtyZero(toRefundDetail && toRefundDetail.qty);
|
||||
return !this.pos.isProductQtyZero(toRefundDetail && toRefundDetail.qty);
|
||||
}
|
||||
getFormattedToRefundQty() {
|
||||
const toRefundDetail = this.getToRefundDetail();
|
||||
|
||||
@@ -54,7 +54,7 @@ export class TicketScreen extends Component {
|
||||
this.numberBuffer.use({
|
||||
triggerAtInput: (event) => this._onUpdateSelectedOrderline(event),
|
||||
});
|
||||
this._state = this.pos.globalState.TICKET_SCREEN_STATE;
|
||||
this._state = this.pos.TICKET_SCREEN_STATE;
|
||||
this.state = useState({
|
||||
showSearchBar: !this.ui.isSmall,
|
||||
});
|
||||
@@ -62,7 +62,7 @@ export class TicketScreen extends Component {
|
||||
? this._state.ui
|
||||
: {
|
||||
selectedSyncedOrderId: null,
|
||||
searchDetails: this.pos.globalState.getDefaultSearchDetails(),
|
||||
searchDetails: this.pos.getDefaultSearchDetails(),
|
||||
filter: null,
|
||||
selectedOrderlineIds: {},
|
||||
};
|
||||
@@ -112,15 +112,13 @@ export class TicketScreen extends Component {
|
||||
}
|
||||
}
|
||||
onCreateNewOrder() {
|
||||
this.pos.globalState.add_new_order();
|
||||
this.pos.add_new_order();
|
||||
this.pos.showScreen("ProductScreen");
|
||||
}
|
||||
_selectNextOrder(currentOrder) {
|
||||
const currentOrderIndex = this._getOrderList().indexOf(currentOrder);
|
||||
const orderList = this._getOrderList();
|
||||
this.pos.globalState.set_order(
|
||||
orderList[currentOrderIndex + 1] || orderList[currentOrderIndex - 1]
|
||||
);
|
||||
this.pos.set_order(orderList[currentOrderIndex + 1] || orderList[currentOrderIndex - 1]);
|
||||
}
|
||||
async onDeleteOrder(order) {
|
||||
const screen = order.get_screen_data();
|
||||
@@ -142,18 +140,17 @@ export class TicketScreen extends Component {
|
||||
return;
|
||||
}
|
||||
}
|
||||
const { globalState } = this.pos;
|
||||
if (order && (await this._onBeforeDeleteOrder(order))) {
|
||||
if (Object.keys(order.lastOrderPrepaChange).length > 0) {
|
||||
await this.pos.sendOrderInPreparation(order, true);
|
||||
}
|
||||
if (order === globalState.get_order()) {
|
||||
if (order === this.pos.get_order()) {
|
||||
this._selectNextOrder(order);
|
||||
}
|
||||
globalState.removeOrder(order);
|
||||
this.pos.removeOrder(order);
|
||||
}
|
||||
if (globalState.isOpenOrderShareable()) {
|
||||
globalState._removeOrdersFromServer();
|
||||
if (this.pos.isOpenOrderShareable()) {
|
||||
this.pos._removeOrdersFromServer();
|
||||
}
|
||||
}
|
||||
async onNextPage() {
|
||||
@@ -169,7 +166,7 @@ export class TicketScreen extends Component {
|
||||
}
|
||||
}
|
||||
async onInvoiceOrder(orderId) {
|
||||
this.pos.globalState._invalidateSyncedOrdersCache([orderId]);
|
||||
this.pos._invalidateSyncedOrdersCache([orderId]);
|
||||
await this._fetchSyncedOrders();
|
||||
}
|
||||
onClickOrderline(orderline) {
|
||||
@@ -179,7 +176,7 @@ export class TicketScreen extends Component {
|
||||
}
|
||||
onClickRefundOrderUid(orderUid) {
|
||||
// Open the refund order.
|
||||
const refundOrder = this.pos.globalState.orders.find((order) => order.uid == orderUid);
|
||||
const refundOrder = this.pos.orders.find((order) => order.uid == orderUid);
|
||||
if (refundOrder) {
|
||||
this._setOrder(refundOrder);
|
||||
}
|
||||
@@ -259,10 +256,9 @@ export class TicketScreen extends Component {
|
||||
? this.props.destinationOrder
|
||||
: this._getEmptyOrder(partner);
|
||||
|
||||
const { globalState } = this.pos;
|
||||
// Add orderline for each toRefundDetail to the destinationOrder.
|
||||
for (const refundDetail of allToRefundDetails) {
|
||||
const product = globalState.db.get_product_by_id(refundDetail.orderline.productId);
|
||||
const product = this.pos.db.get_product_by_id(refundDetail.orderline.productId);
|
||||
const options = this._prepareRefundOrderlineOptions(refundDetail);
|
||||
await destinationOrder.add_product(product, options);
|
||||
refundDetail.destinationOrderUid = destinationOrder.uid;
|
||||
@@ -274,8 +270,8 @@ export class TicketScreen extends Component {
|
||||
destinationOrder.updatePricelist(partner);
|
||||
}
|
||||
|
||||
if (globalState.get_order().cid !== destinationOrder.cid) {
|
||||
globalState.set_order(destinationOrder);
|
||||
if (this.pos.get_order().cid !== destinationOrder.cid) {
|
||||
this.pos.set_order(destinationOrder);
|
||||
}
|
||||
|
||||
this.pos.closeScreen();
|
||||
@@ -363,7 +359,7 @@ export class TicketScreen extends Component {
|
||||
const productScreenStatus = this._getScreenToStatusMap().ProductScreen;
|
||||
return (
|
||||
order.get_orderlines().length === 0 &&
|
||||
this.pos.globalState.get_order_list().length === 1 &&
|
||||
this.pos.get_order_list().length === 1 &&
|
||||
status === productScreenStatus &&
|
||||
order.get_paymentlines().length === 0
|
||||
);
|
||||
@@ -387,12 +383,12 @@ export class TicketScreen extends Component {
|
||||
const selectedOrder = this.getSelectedSyncedOrder();
|
||||
return selectedOrder ? order.backendId == selectedOrder.backendId : false;
|
||||
} else {
|
||||
const activeOrder = this.pos.globalState.get_order();
|
||||
const activeOrder = this.pos.get_order();
|
||||
return activeOrder ? activeOrder.uid == order.uid : false;
|
||||
}
|
||||
}
|
||||
showCardholderName() {
|
||||
return this.pos.globalState.payment_methods.some((method) => method.use_payment_terminal);
|
||||
return this.pos.payment_methods.some((method) => method.use_payment_terminal);
|
||||
}
|
||||
getSearchBarConfig() {
|
||||
return {
|
||||
@@ -426,7 +422,7 @@ export class TicketScreen extends Component {
|
||||
if (this._doesOrderHaveSoleItem(order)) {
|
||||
return true;
|
||||
}
|
||||
const total = Object.values(this.pos.globalState.toRefundLines)
|
||||
const total = Object.values(this.pos.toRefundLines)
|
||||
.filter(
|
||||
(toRefundDetail) =>
|
||||
toRefundDetail.orderline.orderUid === order.uid &&
|
||||
@@ -434,7 +430,7 @@ export class TicketScreen extends Component {
|
||||
)
|
||||
.map((toRefundDetail) => toRefundDetail.qty)
|
||||
.reduce((acc, val) => acc + val, 0);
|
||||
return !this.pos.globalState.isProductQtyZero(total);
|
||||
return !this.pos.isProductQtyZero(total);
|
||||
}
|
||||
//#endregion
|
||||
//#region PRIVATE METHODS
|
||||
@@ -449,7 +445,7 @@ export class TicketScreen extends Component {
|
||||
_getEmptyOrder(partner) {
|
||||
let emptyOrderForPartner = null;
|
||||
let emptyOrder = null;
|
||||
for (const order of this.pos.globalState.orders) {
|
||||
for (const order of this.pos.orders) {
|
||||
if (order.get_orderlines().length === 0 && order.get_paymentlines().length === 0) {
|
||||
if (order.get_partner() === partner) {
|
||||
emptyOrderForPartner = order;
|
||||
@@ -460,7 +456,7 @@ export class TicketScreen extends Component {
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptyOrderForPartner || emptyOrder || this.pos.globalState.add_new_order();
|
||||
return emptyOrderForPartner || emptyOrder || this.pos.add_new_order();
|
||||
}
|
||||
_doesOrderHaveSoleItem(order) {
|
||||
const orderlines = order.get_orderlines();
|
||||
@@ -469,7 +465,7 @@ export class TicketScreen extends Component {
|
||||
}
|
||||
const theOrderline = orderlines[0];
|
||||
const refundableQty = theOrderline.get_quantity() - theOrderline.refunded_qty;
|
||||
return this.pos.globalState.isProductQtyZero(refundableQty - 1);
|
||||
return this.pos.isProductQtyZero(refundableQty - 1);
|
||||
}
|
||||
_prepareAutoRefundOnOrder(order) {
|
||||
const selectedOrderlineId = this.getSelectedOrderlineId();
|
||||
@@ -480,7 +476,7 @@ export class TicketScreen extends Component {
|
||||
|
||||
const toRefundDetail = this._getToRefundDetail(orderline);
|
||||
const refundableQty = orderline.get_quantity() - orderline.refunded_qty;
|
||||
if (this.pos.globalState.isProductQtyZero(refundableQty - 1) && toRefundDetail.qty === 0) {
|
||||
if (this.pos.isProductQtyZero(refundableQty - 1) && toRefundDetail.qty === 0) {
|
||||
toRefundDetail.qty = 1;
|
||||
}
|
||||
return true;
|
||||
@@ -493,7 +489,7 @@ export class TicketScreen extends Component {
|
||||
* @returns
|
||||
*/
|
||||
_getToRefundDetail(orderline) {
|
||||
const { toRefundLines } = this.pos.globalState;
|
||||
const { toRefundLines } = this.pos;
|
||||
if (orderline.id in toRefundLines) {
|
||||
return toRefundLines[orderline.id];
|
||||
}
|
||||
@@ -529,9 +525,9 @@ export class TicketScreen extends Component {
|
||||
* @returns {Array} refundableDetails
|
||||
*/
|
||||
_getRefundableDetails(partner) {
|
||||
return Object.values(this.pos.globalState.toRefundLines).filter(
|
||||
return Object.values(this.pos.toRefundLines).filter(
|
||||
({ qty, orderline, destinationOrderUid }) =>
|
||||
!this.pos.globalState.isProductQtyZero(qty) &&
|
||||
!this.pos.isProductQtyZero(qty) &&
|
||||
(partner ? orderline.orderPartnerId == partner.id : true) &&
|
||||
!destinationOrderUid
|
||||
);
|
||||
@@ -555,15 +551,14 @@ export class TicketScreen extends Component {
|
||||
};
|
||||
}
|
||||
_setOrder(order) {
|
||||
const { globalState } = this.pos;
|
||||
if (globalState.isOpenOrderShareable()) {
|
||||
globalState.sendDraftToServer();
|
||||
if (this.pos.isOpenOrderShareable()) {
|
||||
this.pos.sendDraftToServer();
|
||||
}
|
||||
globalState.set_order(order);
|
||||
this.pos.set_order(order);
|
||||
this.pos.closeScreen();
|
||||
}
|
||||
_getOrderList() {
|
||||
return this.pos.globalState.get_order_list();
|
||||
return this.pos.get_order_list();
|
||||
}
|
||||
_getFilterOptions() {
|
||||
const orderStates = this._getOrderStates();
|
||||
@@ -662,12 +657,11 @@ export class TicketScreen extends Component {
|
||||
* order is not fetched anymore, instead, we use info from cache.
|
||||
*/
|
||||
async _fetchSyncedOrders() {
|
||||
const { globalState } = this.pos;
|
||||
const domain = this._computeSyncedOrdersDomain();
|
||||
const limit = this._state.syncedOrders.nPerPage;
|
||||
const offset =
|
||||
(this._state.syncedOrders.currentPage - 1) * this._state.syncedOrders.nPerPage;
|
||||
const config_id = globalState.config.id;
|
||||
const config_id = this.pos.config.id;
|
||||
const { ordersInfo, totalCount } = await this.orm.call(
|
||||
"pos.order",
|
||||
"search_paid_order_ids",
|
||||
@@ -686,14 +680,14 @@ export class TicketScreen extends Component {
|
||||
if (idsToLoad.length > 0) {
|
||||
const fetchedOrders = await this.orm.call("pos.order", "export_for_ui", [idsToLoad]);
|
||||
// Check for missing products and partners and load them in the PoS
|
||||
await globalState._loadMissingProducts(fetchedOrders);
|
||||
await globalState._loadMissingPartners(fetchedOrders);
|
||||
await this.pos._loadMissingProducts(fetchedOrders);
|
||||
await this.pos._loadMissingPartners(fetchedOrders);
|
||||
// Cache these fetched orders so that next time, no need to fetch
|
||||
// them again, unless invalidated. See `_onInvoiceOrder`.
|
||||
fetchedOrders.forEach((order) => {
|
||||
this._state.syncedOrders.cache[order.id] = new Order(
|
||||
{},
|
||||
{ pos: globalState, json: order }
|
||||
{ pos: this.pos, json: order }
|
||||
);
|
||||
});
|
||||
//Update the datetime indicator of the cache refresh
|
||||
|
||||
@@ -18,7 +18,7 @@ export class CashOpeningPopup extends AbstractAwaitablePopup {
|
||||
this.pos = usePos();
|
||||
this.state = useState({
|
||||
notes: "",
|
||||
openingCash: this.pos.globalState.pos_session.cash_register_balance_start || 0,
|
||||
openingCash: this.pos.pos_session.cash_register_balance_start || 0,
|
||||
});
|
||||
this.popup = useService("popup");
|
||||
this.orm = useService("orm");
|
||||
@@ -27,10 +27,10 @@ export class CashOpeningPopup extends AbstractAwaitablePopup {
|
||||
}
|
||||
//@override
|
||||
async confirm() {
|
||||
this.pos.globalState.pos_session.cash_register_balance_start = this.state.openingCash;
|
||||
this.pos.globalState.pos_session.state = "opened";
|
||||
this.pos.pos_session.cash_register_balance_start = this.state.openingCash;
|
||||
this.pos.pos_session.state = "opened";
|
||||
this.orm.call("pos.session", "set_cashbox_pos", [
|
||||
this.pos.globalState.pos_session.id,
|
||||
this.pos.pos_session.id,
|
||||
this.state.openingCash,
|
||||
this.state.notes,
|
||||
]);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -11,8 +11,8 @@ import { registry } from "@web/core/registry";
|
||||
export const contextualUtilsService = {
|
||||
dependencies: ["pos"],
|
||||
start(env, { pos }) {
|
||||
const currency = pos.globalState.currency;
|
||||
const productUoMDecimals = pos.globalState.dp["Product Unit of Measure"];
|
||||
const currency = pos.currency;
|
||||
const productUoMDecimals = pos.dp["Product Unit of Measure"];
|
||||
|
||||
const formatProductQty = (qty) => {
|
||||
return formatFloat(qty, { digits: [true, productUoMDecimals] });
|
||||
|
||||
+6
-6
@@ -11,11 +11,11 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
|
||||
setup() {
|
||||
super.setup();
|
||||
this.pos = usePos();
|
||||
this.currency = this.pos.globalState.currency;
|
||||
this.currency = this.pos.currency;
|
||||
this.state = useState({
|
||||
moneyDetails: this.props.moneyDetails
|
||||
? { ...this.props.moneyDetails }
|
||||
: Object.fromEntries(this.pos.globalState.bills.map((bill) => [bill.value, 0])),
|
||||
: Object.fromEntries(this.pos.bills.map((bill) => [bill.value, 0])),
|
||||
total: this.props.total ? this.props.total : 0,
|
||||
action: this.props.action ? this.props.action : null,
|
||||
});
|
||||
@@ -42,7 +42,7 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
|
||||
let moneyDetailsNotes = !floatIsZero(this.state.total, this.currency.decimal_places)
|
||||
? "Money details: \n"
|
||||
: null;
|
||||
this.pos.globalState.bills.forEach((bill) => {
|
||||
this.pos.bills.forEach((bill) => {
|
||||
if (this.state.moneyDetails[bill.value]) {
|
||||
moneyDetailsNotes += ` - ${
|
||||
this.state.moneyDetails[bill.value]
|
||||
@@ -59,10 +59,10 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
|
||||
async cancel() {
|
||||
super.cancel();
|
||||
if (
|
||||
this.pos.globalState.config.iface_cashdrawer &&
|
||||
this.pos.globalState.hardwareProxy.connectionInfo.status === "connected"
|
||||
this.pos.config.iface_cashdrawer &&
|
||||
this.pos.hardwareProxy.connectionInfo.status === "connected"
|
||||
) {
|
||||
this.pos.globalState.logEmployeeMessage(this.state.action, "ACTION_CANCELLED");
|
||||
this.pos.logEmployeeMessage(this.state.action, "ACTION_CANCELLED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<t t-set="html_data" t-value="{'style': 'height: 100%;'}"/>
|
||||
<t t-set="title">Point of Sale Tests</t>
|
||||
<t t-set="head">
|
||||
<!-- we need session_info in order to properly instantiate PosGlobalState -->
|
||||
<!-- we need session_info in order to properly instantiate PosStore-->
|
||||
<script type="text/javascript">
|
||||
var odoo = <t t-out="json.dumps({
|
||||
'csrf_token': request.csrf_token(None),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/** @odoo-module */
|
||||
import { register_payment_method, Payment } from "@point_of_sale/app/store/models";
|
||||
import { register_payment_method } from "@point_of_sale/app/store/pos_store";
|
||||
import { Payment } from "@point_of_sale/app/store/models";
|
||||
import { PaymentAdyen } from "@pos_adyen/js/payment_adyen";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ export class DiscountButton extends Component {
|
||||
var self = this;
|
||||
const { confirmed, payload } = await this.popup.add(NumberPopup, {
|
||||
title: this.env._t("Discount Percentage"),
|
||||
startingValue: this.pos.globalState.config.discount_pc,
|
||||
startingValue: this.pos.config.discount_pc,
|
||||
isInputSelected: true,
|
||||
});
|
||||
if (confirmed) {
|
||||
@@ -29,10 +29,9 @@ export class DiscountButton extends Component {
|
||||
}
|
||||
|
||||
async apply_discount(pc) {
|
||||
const { globalState } = this.pos;
|
||||
const order = globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
const lines = order.get_orderlines();
|
||||
const product = globalState.db.get_product_by_id(globalState.config.discount_product_id[0]);
|
||||
const product = this.pos.db.get_product_by_id(this.pos.config.discount_product_id[0]);
|
||||
if (product === undefined) {
|
||||
await this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("No discount product found"),
|
||||
@@ -62,8 +61,8 @@ export class DiscountButton extends Component {
|
||||
tax_ids_array,
|
||||
lines.filter(
|
||||
(line) =>
|
||||
!globalState.config.tip_product_id ||
|
||||
line.product.id !== globalState.config.tip_product_id[0]
|
||||
!this.pos.config.tip_product_id ||
|
||||
line.product.id !== this.pos.config.tip_product_id[0]
|
||||
)
|
||||
);
|
||||
|
||||
@@ -81,7 +80,7 @@ export class DiscountButton extends Component {
|
||||
? sprintf(
|
||||
this.env._t("Tax: %s"),
|
||||
tax_ids_array
|
||||
.map((taxId) => globalState.taxes_by_id[taxId].amount + "%")
|
||||
.map((taxId) => this.pos.taxes_by_id[taxId].amount + "%")
|
||||
.join(", ")
|
||||
)
|
||||
: this.env._t("No tax")),
|
||||
@@ -97,7 +96,7 @@ export class DiscountButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: DiscountButton,
|
||||
condition: function () {
|
||||
const { module_pos_discount, discount_product_id } = this.pos.globalState.config;
|
||||
const { module_pos_discount, discount_product_id } = this.pos.config;
|
||||
return module_pos_discount && discount_product_id;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { PosGlobalState } from "@point_of_sale/app/store/models";
|
||||
import { PosStore } from "@point_of_sale/app/store/pos_store";
|
||||
import { EpsonPrinter } from "@pos_epson_printer/js/epson_printer";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(PosGlobalState.prototype, "pos_epson_printer.PosGlobalState", {
|
||||
patch(PosStore.prototype, "pos_epson_printer.PosStore", {
|
||||
after_load_server_data() {
|
||||
var self = this;
|
||||
return this._super(...arguments).then(function () {
|
||||
|
||||
@@ -5,27 +5,25 @@ import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(Navbar.prototype, "pos_hr.Navbar", {
|
||||
get showCashMoveButton() {
|
||||
const { cashier } = this.pos.globalState;
|
||||
const { cashier } = this.pos;
|
||||
return this._super(...arguments) && (!cashier || cashier.role == "manager");
|
||||
},
|
||||
get showCloseSessionButton() {
|
||||
return (
|
||||
!this.pos.globalState.config.module_pos_hr ||
|
||||
(this.pos.globalState.get_cashier().role === "manager" &&
|
||||
this.pos.globalState.get_cashier().user_id) ||
|
||||
this.pos.globalState.get_cashier_user_id() === this.pos.globalState.user.id
|
||||
!this.pos.config.module_pos_hr ||
|
||||
(this.pos.get_cashier().role === "manager" && this.pos.get_cashier().user_id) ||
|
||||
this.pos.get_cashier_user_id() === this.pos.user.id
|
||||
);
|
||||
},
|
||||
get showBackendButton() {
|
||||
return (
|
||||
!this.pos.globalState.config.module_pos_hr ||
|
||||
(this.pos.globalState.get_cashier().role === "manager" &&
|
||||
this.pos.globalState.get_cashier().user_id) ||
|
||||
this.pos.globalState.get_cashier_user_id() === this.pos.globalState.user.id
|
||||
!this.pos.config.module_pos_hr ||
|
||||
(this.pos.get_cashier().role === "manager" && this.pos.get_cashier().user_id) ||
|
||||
this.pos.get_cashier_user_id() === this.pos.user.id
|
||||
);
|
||||
},
|
||||
async showLoginScreen() {
|
||||
this.pos.globalState.reset_cashier();
|
||||
this.pos.reset_cashier();
|
||||
await this.pos.showTempScreen("LoginScreen");
|
||||
},
|
||||
});
|
||||
|
||||
@@ -4,22 +4,22 @@
|
||||
<t t-name="pos_hr.Navbar" t-inherit="point_of_sale.Navbar" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//li[hasclass('backend-button')]" position="attributes">
|
||||
<attribute name="t-if">
|
||||
showBackendButton
|
||||
!pos.config.module_pos_hr or pos.get_cashier().role === 'manager' or pos.get_cashier_user_id() === pos.user.id
|
||||
</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//li[hasclass('close-button')]" position="attributes">
|
||||
<attribute name="t-if">
|
||||
showCloseSessionButton
|
||||
!pos.config.module_pos_hr or pos.get_cashier().role === 'manager' or pos.get_cashier_user_id() === pos.user.id
|
||||
</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//li[hasclass('backend-button')]" position="after">
|
||||
<li t-if="pos.globalState.config.module_pos_hr" class="menu-item navbar-button lock-button" t-on-click="showLoginScreen">
|
||||
<span>
|
||||
Lock
|
||||
</span>
|
||||
</li>
|
||||
<li t-if="pos.config.module_pos_hr" class="menu-item navbar-button lock-button" t-on-click="showLoginScreen">
|
||||
<span>
|
||||
Lock
|
||||
</span>
|
||||
</li>
|
||||
</xpath>
|
||||
</t>
|
||||
|
||||
|
||||
@@ -6,16 +6,81 @@ import { PosStore } from "@point_of_sale/app/store/pos_store";
|
||||
patch(PosStore.prototype, "pos_hr.PosStore", {
|
||||
async setup() {
|
||||
await this._super(...arguments);
|
||||
if (this.globalState.config.module_pos_hr) {
|
||||
if (this.config.module_pos_hr) {
|
||||
this.showTempScreen("LoginScreen");
|
||||
}
|
||||
},
|
||||
async _processData(loadedData) {
|
||||
await this._super(...arguments);
|
||||
if (this.config.module_pos_hr) {
|
||||
this.employees = loadedData["hr.employee"];
|
||||
this.employee_by_id = loadedData["employee_by_id"];
|
||||
this.reset_cashier();
|
||||
}
|
||||
},
|
||||
async after_load_server_data() {
|
||||
await this._super(...arguments);
|
||||
if (this.config.module_pos_hr) {
|
||||
this.hasLoggedIn = !this.config.module_pos_hr;
|
||||
}
|
||||
},
|
||||
reset_cashier() {
|
||||
this.cashier = {
|
||||
name: null,
|
||||
id: null,
|
||||
barcode: null,
|
||||
user_id: null,
|
||||
pin: null,
|
||||
role: null,
|
||||
};
|
||||
},
|
||||
set_cashier(employee) {
|
||||
this.cashier = employee;
|
||||
const selectedOrder = this.get_order();
|
||||
if (selectedOrder && !selectedOrder.get_orderlines().length) {
|
||||
// Order without lines can be considered to be un-owned by any employee.
|
||||
// We set the cashier on that order to the currently set employee.
|
||||
selectedOrder.cashier = employee;
|
||||
}
|
||||
if (!this.cashierHasPriceControlRights() && this.numpadMode === "price") {
|
||||
this.numpadMode = "quantity";
|
||||
}
|
||||
},
|
||||
/**{name: null, id: null, barcode: null, user_id:null, pin:null}
|
||||
* If pos_hr is activated, return {name: string, id: int, barcode: string, pin: string, user_id: int}
|
||||
* @returns {null|*}
|
||||
*/
|
||||
get_cashier() {
|
||||
if (this.config.module_pos_hr) {
|
||||
return this.cashier;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
get_cashier_user_id() {
|
||||
if (this.config.module_pos_hr) {
|
||||
return this.cashier.user_id ? this.cashier.user_id : null;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
async logEmployeeMessage(action, message) {
|
||||
if (!this.config.module_pos_hr) {
|
||||
this._super(...arguments);
|
||||
return;
|
||||
}
|
||||
await this.orm.call("pos.session", "log_partner_message", [
|
||||
this.pos_session.id,
|
||||
this.cashier.work_contact_id,
|
||||
action,
|
||||
message,
|
||||
]);
|
||||
},
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
shouldShowCashControl() {
|
||||
if (this.globalState.config.module_pos_hr) {
|
||||
return this._super(...arguments) && this.globalState.hasLoggedIn;
|
||||
if (this.config.module_pos_hr) {
|
||||
return this._super(...arguments) && this.hasLoggedIn;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
|
||||
@@ -11,15 +11,15 @@ patch(CashierName.prototype, "pos_hr.CashierName", {
|
||||
},
|
||||
//@Override
|
||||
get avatar() {
|
||||
if (this.pos.globalState.config.module_pos_hr) {
|
||||
const cashier = this.pos.globalState.get_cashier();
|
||||
if (this.pos.config.module_pos_hr) {
|
||||
const cashier = this.pos.get_cashier();
|
||||
return `/web/image/hr.employee/${cashier.id}/avatar_128`;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
//@Override
|
||||
get cssClass() {
|
||||
if (this.pos.globalState.config.module_pos_hr) {
|
||||
if (this.pos.config.module_pos_hr) {
|
||||
return { oe_status: true };
|
||||
}
|
||||
return this._super(...arguments);
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { Chrome } from "@point_of_sale/app/pos_app";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(Chrome.prototype, "pos_hr.Chrome", {
|
||||
get showCashMoveButton() {
|
||||
const { cashier } = this.pos;
|
||||
return this._super(...arguments) && (!cashier || cashier.role == "manager");
|
||||
},
|
||||
});
|
||||
@@ -10,7 +10,7 @@ export class HeaderLockButton extends Component {
|
||||
this.pos = usePos();
|
||||
}
|
||||
async showLoginScreen() {
|
||||
this.pos.globalState.reset_cashier();
|
||||
this.pos.reset_cashier();
|
||||
await this.pos.showTempScreen("LoginScreen");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ export class LoginScreen extends Component {
|
||||
back() {
|
||||
this.props.resolve({ confirmed: false, payload: false });
|
||||
this.pos.closeTempScreen();
|
||||
this.pos.globalState.hasLoggedIn = true;
|
||||
this.pos.hasLoggedIn = true;
|
||||
this.pos.openCashControl();
|
||||
}
|
||||
|
||||
get shopName() {
|
||||
return this.pos.globalState.config.name;
|
||||
return this.pos.config.name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(PaymentScreen.prototype, "pos_hr.PaymentScreen", {
|
||||
async _finalizeValidation() {
|
||||
this.currentOrder.cashier = this.pos.globalState.get_cashier();
|
||||
this.currentOrder.cashier = this.pos.get_cashier();
|
||||
await this._super(...arguments);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -14,19 +14,17 @@ export function useCashierSelector(
|
||||
{ onCashierChanged, exclusive } = { onCashierChanged: () => {}, exclusive: false }
|
||||
) {
|
||||
const popup = useService("popup");
|
||||
const { globalState } = usePos();
|
||||
const pos = usePos();
|
||||
useBarcodeReader(
|
||||
{
|
||||
async cashier(code) {
|
||||
const employee = globalState.employees.find(
|
||||
(emp) => emp.barcode === Sha1.hash(code.code)
|
||||
);
|
||||
const employee = pos.employees.find((emp) => emp.barcode === Sha1.hash(code.code));
|
||||
if (
|
||||
employee &&
|
||||
employee !== globalState.get_cashier() &&
|
||||
employee !== pos.get_cashier() &&
|
||||
(!employee.pin || (await checkPin(employee)))
|
||||
) {
|
||||
globalState.set_cashier(employee);
|
||||
pos.set_cashier(employee);
|
||||
if (onCashierChanged) {
|
||||
onCashierChanged();
|
||||
}
|
||||
@@ -60,9 +58,9 @@ export function useCashierSelector(
|
||||
* Select a cashier, the returning value will either be an object or nothing (undefined)
|
||||
*/
|
||||
return async function selectCashier() {
|
||||
if (globalState.config.module_pos_hr) {
|
||||
const employeesList = globalState.employees
|
||||
.filter((employee) => employee.id !== globalState.get_cashier().id)
|
||||
if (pos.config.module_pos_hr) {
|
||||
const employeesList = pos.employees
|
||||
.filter((employee) => employee.id !== pos.get_cashier().id)
|
||||
.map((employee) => {
|
||||
return {
|
||||
id: employee.id,
|
||||
@@ -80,7 +78,7 @@ export function useCashierSelector(
|
||||
return;
|
||||
}
|
||||
|
||||
globalState.set_cashier(employee);
|
||||
pos.set_cashier(employee);
|
||||
if (onCashierChanged) {
|
||||
onCashierChanged();
|
||||
}
|
||||
|
||||
@@ -1,75 +1,8 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { PosGlobalState, Order } from "@point_of_sale/app/store/models";
|
||||
import { Order } from "@point_of_sale/app/store/models";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(PosGlobalState.prototype, "pos_hr.PosGlobalState", {
|
||||
async _processData(loadedData) {
|
||||
await this._super(...arguments);
|
||||
if (this.config.module_pos_hr) {
|
||||
this.employees = loadedData["hr.employee"];
|
||||
this.employee_by_id = loadedData["employee_by_id"];
|
||||
this.reset_cashier();
|
||||
}
|
||||
},
|
||||
async after_load_server_data() {
|
||||
await this._super(...arguments);
|
||||
if (this.config.module_pos_hr) {
|
||||
this.hasLoggedIn = !this.config.module_pos_hr;
|
||||
}
|
||||
},
|
||||
reset_cashier() {
|
||||
this.cashier = {
|
||||
name: null,
|
||||
id: null,
|
||||
barcode: null,
|
||||
user_id: null,
|
||||
pin: null,
|
||||
role: null,
|
||||
};
|
||||
},
|
||||
set_cashier(employee) {
|
||||
this.cashier = employee;
|
||||
const selectedOrder = this.get_order();
|
||||
if (selectedOrder && !selectedOrder.get_orderlines().length) {
|
||||
// Order without lines can be considered to be un-owned by any employee.
|
||||
// We set the cashier on that order to the currently set employee.
|
||||
selectedOrder.cashier = employee;
|
||||
}
|
||||
if (!this.cashierHasPriceControlRights() && this.numpadMode === "price") {
|
||||
this.numpadMode = "quantity";
|
||||
}
|
||||
},
|
||||
/**{name: null, id: null, barcode: null, user_id:null, pin:null}
|
||||
* If pos_hr is activated, return {name: string, id: int, barcode: string, pin: string, user_id: int}
|
||||
* @returns {null|*}
|
||||
*/
|
||||
get_cashier() {
|
||||
if (this.config.module_pos_hr) {
|
||||
return this.cashier;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
get_cashier_user_id() {
|
||||
if (this.config.module_pos_hr) {
|
||||
return this.cashier.user_id ? this.cashier.user_id : null;
|
||||
}
|
||||
return this._super(...arguments);
|
||||
},
|
||||
async logEmployeeMessage(action, message) {
|
||||
if (!this.config.module_pos_hr) {
|
||||
this._super(...arguments);
|
||||
return;
|
||||
}
|
||||
await this.orm.call("pos.session", "log_partner_message", [
|
||||
this.pos_session.id,
|
||||
this.cashier.work_contact_id,
|
||||
action,
|
||||
message,
|
||||
]);
|
||||
},
|
||||
});
|
||||
|
||||
patch(Order.prototype, "pos_hr.Order", {
|
||||
setup(options) {
|
||||
this._super(...arguments);
|
||||
|
||||
@@ -6,13 +6,18 @@ import { _t } from "@web/core/l10n/translation";
|
||||
import { SelectionPopup } from "@point_of_sale/app/utils/input_popups/selection_popup";
|
||||
import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
|
||||
import { TextInputPopup } from "@point_of_sale/app/utils/input_popups/text_input_popup";
|
||||
import { Domain, InvalidDomainError } from "@web/core/domain";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { PosLoyaltyCard } from "@pos_loyalty/js/Loyalty";
|
||||
|
||||
const COUPON_CACHE_MAX_SIZE = 4096; // Maximum coupon cache size, prevents long run memory issues and (to some extent) invalid data
|
||||
|
||||
patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
async addProductFromUi(product, options) {
|
||||
const _super = this._super;
|
||||
const order = this.globalState.get_order();
|
||||
const linkedProgramIds = this.globalState.productId2ProgramIds[product.id] || [];
|
||||
const linkedPrograms = linkedProgramIds.map((id) => this.globalState.program_by_id[id]);
|
||||
const order = this.get_order();
|
||||
const linkedProgramIds = this.productId2ProgramIds[product.id] || [];
|
||||
const linkedPrograms = linkedProgramIds.map((id) => this.program_by_id[id]);
|
||||
let selectedProgram = null;
|
||||
if (linkedPrograms.length > 1) {
|
||||
const { confirmed, payload: program } = await this.popup.add(SelectionPopup, {
|
||||
@@ -32,7 +37,7 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
} else if (linkedPrograms.length === 1) {
|
||||
selectedProgram = linkedPrograms[0];
|
||||
}
|
||||
const orderTotal = this.globalState.get_order().get_total_with_tax();
|
||||
const orderTotal = this.get_order().get_total_with_tax();
|
||||
if (
|
||||
selectedProgram &&
|
||||
["gift_card", "ewallet"].includes(selectedProgram.program_type) &&
|
||||
@@ -82,15 +87,12 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
options.eWalletGiftCardProgram = program;
|
||||
|
||||
// If gift card program setting is 'scan_use', ask for the code.
|
||||
if (this.globalState.config.gift_card_settings == "scan_use") {
|
||||
const { confirmed, payload: code } = await this.globalState.env.services.popup.add(
|
||||
TextInputPopup,
|
||||
{
|
||||
title: _t("Generate a Gift Card"),
|
||||
startingValue: "",
|
||||
placeholder: _t("Enter the gift card code"),
|
||||
}
|
||||
);
|
||||
if (this.config.gift_card_settings == "scan_use") {
|
||||
const { confirmed, payload: code } = await this.env.services.popup.add(TextInputPopup, {
|
||||
title: _t("Generate a Gift Card"),
|
||||
startingValue: "",
|
||||
placeholder: _t("Enter the gift card code"),
|
||||
});
|
||||
if (!confirmed) {
|
||||
return false;
|
||||
}
|
||||
@@ -124,9 +126,7 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
options.giftCardId = giftCard.id;
|
||||
}
|
||||
} else {
|
||||
this.globalState.env.services.pos_notification.add(
|
||||
"Please enter a valid gift card code."
|
||||
);
|
||||
this.env.services.pos_notification.add("Please enter a valid gift card code.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -144,7 +144,7 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
* it comes with the corresponding reward product line.
|
||||
*/
|
||||
getPotentialFreeProductRewards() {
|
||||
const order = this.globalState.get_order();
|
||||
const order = this.get_order();
|
||||
const allCouponPrograms = Object.values(order.couponPointChanges)
|
||||
.map((pe) => {
|
||||
return {
|
||||
@@ -162,7 +162,7 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
);
|
||||
const result = [];
|
||||
for (const couponProgram of allCouponPrograms) {
|
||||
const program = this.globalState.program_by_id[couponProgram.program_id];
|
||||
const program = this.program_by_id[couponProgram.program_id];
|
||||
const points = order._getRealCouponPoints(couponProgram.coupon_id);
|
||||
const hasLine = order.orderlines.filter((line) => !line.is_reward_line).length > 0;
|
||||
for (const reward of program.rewards.filter(
|
||||
@@ -175,9 +175,7 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
const considerTheReward =
|
||||
program.applies_on !== "both" || (program.applies_on == "both" && hasLine);
|
||||
if (reward.reward_type === "product" && considerTheReward) {
|
||||
const product = this.globalState.db.get_product_by_id(
|
||||
reward.reward_product_ids[0]
|
||||
);
|
||||
const product = this.db.get_product_by_id(reward.reward_product_ids[0]);
|
||||
const potentialQty = order._computePotentialFreeProductQty(
|
||||
reward,
|
||||
product,
|
||||
@@ -196,4 +194,196 @@ patch(PosStore.prototype, "pos_loyalty.PosStore", {
|
||||
}
|
||||
return result;
|
||||
},
|
||||
//@override
|
||||
async _processData(loadedData) {
|
||||
this.couponCache = {};
|
||||
this.partnerId2CouponIds = {};
|
||||
this.rewards = loadedData["loyalty.reward"] || [];
|
||||
|
||||
for (const reward of this.rewards) {
|
||||
reward.all_discount_product_ids = new Set(reward.all_discount_product_ids);
|
||||
}
|
||||
|
||||
await this._super(loadedData);
|
||||
this.productId2ProgramIds = loadedData["product_id_to_program_ids"];
|
||||
this.programs = loadedData["loyalty.program"] || []; //TODO: rename to `loyaltyPrograms` etc
|
||||
this.rules = loadedData["loyalty.rule"] || [];
|
||||
this._loadLoyaltyData();
|
||||
},
|
||||
|
||||
_loadProductProduct(products) {
|
||||
this._super(...arguments);
|
||||
|
||||
for (const reward of this.rewards) {
|
||||
this.compute_discount_product_ids(reward, products);
|
||||
}
|
||||
|
||||
this.rewards = this.rewards.filter(Boolean);
|
||||
},
|
||||
|
||||
compute_discount_product_ids(reward, products) {
|
||||
const reward_product_domain = JSON.parse(reward.reward_product_domain);
|
||||
if (!reward_product_domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
const domain = new Domain(reward_product_domain);
|
||||
|
||||
try {
|
||||
products
|
||||
.filter((product) => domain.contains(product))
|
||||
.forEach((product) => reward.all_discount_product_ids.add(product.id));
|
||||
} catch (error) {
|
||||
if (!(error instanceof InvalidDomainError)) {
|
||||
throw error;
|
||||
}
|
||||
const index = this.rewards.indexOf(reward);
|
||||
if (index != -1) {
|
||||
this.pos.env.services.popup.add(ErrorPopup, {
|
||||
title: _t("A reward could not be loaded"),
|
||||
body: sprintf(
|
||||
_t(
|
||||
'The reward "%s" contain an error in its domain, your domain must be compatible with the PoS client'
|
||||
),
|
||||
this.rewards[index].description
|
||||
),
|
||||
});
|
||||
this.rewards[index] = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_loadLoyaltyData() {
|
||||
this.program_by_id = {};
|
||||
this.reward_by_id = {};
|
||||
|
||||
for (const program of this.programs) {
|
||||
this.program_by_id[program.id] = program;
|
||||
if (program.date_to) {
|
||||
program.date_to = new Date(program.date_to);
|
||||
}
|
||||
program.rules = [];
|
||||
program.rewards = [];
|
||||
}
|
||||
for (const rule of this.rules) {
|
||||
rule.valid_product_ids = new Set(rule.valid_product_ids);
|
||||
rule.program_id = this.program_by_id[rule.program_id[0]];
|
||||
rule.program_id.rules.push(rule);
|
||||
}
|
||||
for (const reward of this.rewards) {
|
||||
this.reward_by_id[reward.id] = reward;
|
||||
reward.program_id = this.program_by_id[reward.program_id[0]];
|
||||
reward.discount_line_product_id = this.db.get_product_by_id(
|
||||
reward.discount_line_product_id[0]
|
||||
);
|
||||
reward.all_discount_product_ids = new Set(reward.all_discount_product_ids);
|
||||
reward.program_id.rewards.push(reward);
|
||||
}
|
||||
},
|
||||
async load_server_data() {
|
||||
await this._super(...arguments);
|
||||
if (this.selectedOrder) {
|
||||
this.selectedOrder._updateRewards();
|
||||
}
|
||||
},
|
||||
set_order(order) {
|
||||
const result = this._super(...arguments);
|
||||
// FIXME - JCB: This is a temporary fix.
|
||||
// When an order is selected, it doesn't always contain the reward lines.
|
||||
// And the list of active programs are not always correct. This is because
|
||||
// of the use of DropPrevious in _updateRewards.
|
||||
if (order) {
|
||||
order._updateRewards();
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Fetches `loyalty.card` records from the server and adds/updates them in our cache.
|
||||
*
|
||||
* @param {domain} domain For the search
|
||||
* @param {int} limit Default to 1
|
||||
*/
|
||||
async fetchCoupons(domain, limit = 1) {
|
||||
const result = await this.env.services.orm.searchRead(
|
||||
"loyalty.card",
|
||||
domain,
|
||||
["id", "points", "code", "partner_id", "program_id"],
|
||||
{ limit }
|
||||
);
|
||||
if (Object.keys(this.couponCache).length + result.length > COUPON_CACHE_MAX_SIZE) {
|
||||
this.couponCache = {};
|
||||
this.partnerId2CouponIds = {};
|
||||
// Make sure that the current order has no invalid data.
|
||||
if (this.selectedOrder) {
|
||||
this.selectedOrder.invalidCoupons = true;
|
||||
}
|
||||
}
|
||||
const couponList = [];
|
||||
for (const dbCoupon of result) {
|
||||
const coupon = new PosLoyaltyCard(
|
||||
dbCoupon.code,
|
||||
dbCoupon.id,
|
||||
dbCoupon.program_id[0],
|
||||
dbCoupon.partner_id[0],
|
||||
dbCoupon.points
|
||||
);
|
||||
this.couponCache[coupon.id] = coupon;
|
||||
this.partnerId2CouponIds[coupon.partner_id] =
|
||||
this.partnerId2CouponIds[coupon.partner_id] || new Set();
|
||||
this.partnerId2CouponIds[coupon.partner_id].add(coupon.id);
|
||||
couponList.push(coupon);
|
||||
}
|
||||
return couponList;
|
||||
},
|
||||
/**
|
||||
* Fetches a loyalty card for the given program and partner, put in cache afterwards
|
||||
* if a matching card is found in the cache, that one is used instead.
|
||||
* If no card is found a local only card will be created until the order is validated.
|
||||
*
|
||||
* @param {int} programId
|
||||
* @param {int} partnerId
|
||||
*/
|
||||
async fetchLoyaltyCard(programId, partnerId) {
|
||||
for (const coupon of Object.values(this.couponCache)) {
|
||||
if (coupon.partner_id === partnerId && coupon.program_id === programId) {
|
||||
return coupon;
|
||||
}
|
||||
}
|
||||
const fetchedCoupons = await this.fetchCoupons([
|
||||
["partner_id", "=", partnerId],
|
||||
["program_id", "=", programId],
|
||||
]);
|
||||
const dbCoupon = fetchedCoupons.length > 0 ? fetchedCoupons[0] : null;
|
||||
return dbCoupon || new PosLoyaltyCard(null, null, programId, partnerId, 0);
|
||||
},
|
||||
getLoyaltyCards(partner) {
|
||||
const loyaltyCards = [];
|
||||
if (this.partnerId2CouponIds[partner.id]) {
|
||||
this.partnerId2CouponIds[partner.id].forEach((couponId) =>
|
||||
loyaltyCards.push(this.couponCache[couponId])
|
||||
);
|
||||
}
|
||||
return loyaltyCards;
|
||||
},
|
||||
addPartners(partners) {
|
||||
const result = this._super(partners);
|
||||
// cache the loyalty cards of the partners
|
||||
for (const partner of partners) {
|
||||
for (const [couponId, { code, program_id, points }] of Object.entries(
|
||||
partner.loyalty_cards || {}
|
||||
)) {
|
||||
this.couponCache[couponId] = new PosLoyaltyCard(
|
||||
code,
|
||||
parseInt(couponId, 10),
|
||||
program_id,
|
||||
partner.id,
|
||||
points
|
||||
);
|
||||
this.partnerId2CouponIds[partner.id] =
|
||||
this.partnerId2CouponIds[partner.id] || new Set();
|
||||
this.partnerId2CouponIds[partner.id].add(couponId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ export class PromoCodeButton extends Component {
|
||||
if (confirmed) {
|
||||
code = code.trim();
|
||||
if (code !== "") {
|
||||
this.pos.globalState.get_order().activateCode(code);
|
||||
this.pos.get_order().activateCode(code);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,7 +32,7 @@ export class PromoCodeButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: PromoCodeButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.programs.some((p) =>
|
||||
return this.pos.programs.some((p) =>
|
||||
["coupons", "promotion", "gift_card", "promo_code"].includes(p.program_type)
|
||||
);
|
||||
},
|
||||
|
||||
@@ -11,17 +11,17 @@ export class ResetProgramsButton extends Component {
|
||||
this.pos = usePos();
|
||||
}
|
||||
_isDisabled() {
|
||||
return !this.pos.globalState.get_order().isProgramsResettable();
|
||||
return !this.pos.get_order().isProgramsResettable();
|
||||
}
|
||||
click() {
|
||||
this.pos.globalState.get_order()._resetPrograms();
|
||||
this.pos.get_order()._resetPrograms();
|
||||
}
|
||||
}
|
||||
|
||||
ProductScreen.addControlButton({
|
||||
component: ResetProgramsButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.programs.some((p) =>
|
||||
return this.pos.programs.some((p) =>
|
||||
["coupons", "promotion"].includes(p.program_type)
|
||||
);
|
||||
},
|
||||
|
||||
@@ -30,7 +30,7 @@ export class RewardButton extends Component {
|
||||
}
|
||||
|
||||
_getPotentialRewards() {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
// Claimable rewards excluding those from eWallet programs.
|
||||
// eWallet rewards are handled in the eWalletButton.
|
||||
let rewards = [];
|
||||
@@ -61,14 +61,14 @@ export class RewardButton extends Component {
|
||||
* @param {Integer} coupon_id
|
||||
*/
|
||||
async _applyReward(reward, coupon_id, potentialQty) {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
order.disabledRewards.delete(reward.id);
|
||||
|
||||
const args = {};
|
||||
if (reward.reward_type === "product" && reward.multi_product) {
|
||||
const productsList = reward.reward_product_ids.map((product_id) => ({
|
||||
id: product_id,
|
||||
label: this.pos.globalState.db.get_product_by_id(product_id).display_name,
|
||||
label: this.pos.db.get_product_by_id(product_id).display_name,
|
||||
item: product_id,
|
||||
}));
|
||||
const { confirmed, payload: selectedProduct } = await this.popup.add(SelectionPopup, {
|
||||
@@ -125,6 +125,6 @@ export class RewardButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: RewardButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.programs.length > 0;
|
||||
return this.pos.programs.length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -23,11 +23,11 @@ export class eWalletButton extends Component {
|
||||
return eWalletRewards;
|
||||
}
|
||||
_getEWalletPrograms() {
|
||||
return this.pos.globalState.programs.filter((p) => p.program_type == "ewallet");
|
||||
return this.pos.programs.filter((p) => p.program_type == "ewallet");
|
||||
}
|
||||
async _onClickWalletButton() {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const eWalletPrograms = this.pos.globalState.programs.filter(
|
||||
const order = this.pos.get_order();
|
||||
const eWalletPrograms = this.pos.programs.filter(
|
||||
(p) => p.program_type == "ewallet"
|
||||
);
|
||||
const orderTotal = order.get_total_with_tax();
|
||||
@@ -50,7 +50,7 @@ export class eWalletButton extends Component {
|
||||
}
|
||||
}
|
||||
if (selectedProgram) {
|
||||
const eWalletProduct = this.pos.globalState.db.get_product_by_id(
|
||||
const eWalletProduct = this.pos.db.get_product_by_id(
|
||||
selectedProgram.trigger_product_ids[0]
|
||||
);
|
||||
this.pos.addProductFromUi(eWalletProduct, {
|
||||
@@ -110,6 +110,6 @@ export class eWalletButton extends Component {
|
||||
ProductScreen.addControlButton({
|
||||
component: eWalletButton,
|
||||
condition: function () {
|
||||
return this.pos.globalState.programs.filter((p) => p.program_type == "ewallet").length > 0;
|
||||
return this.pos.programs.filter((p) => p.program_type == "ewallet").length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
/** @odoo-module **/
|
||||
|
||||
import { Order, Orderline, PosGlobalState } from "@point_of_sale/app/store/models";
|
||||
import { Order, Orderline } from "@point_of_sale/app/store/models";
|
||||
import { Mutex } from "@web/core/utils/concurrency";
|
||||
import concurrency from "web.concurrency";
|
||||
import { roundDecimals, roundPrecision } from "@web/core/utils/numbers";
|
||||
import { _t } from "@web/core/l10n/translation";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
import { ConfirmPopup } from "@point_of_sale/app/utils/confirm_popup/confirm_popup";
|
||||
import { Domain, InvalidDomainError } from "@web/core/domain";
|
||||
import { sprintf } from "@web/core/utils/strings";
|
||||
import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
|
||||
|
||||
// FIXME: Perhaps MutexedDropPrevious can be replaced by the new KeepLast.
|
||||
// > This might require thorough investigation on how _updateRewards work.
|
||||
@@ -17,8 +15,6 @@ import { ErrorPopup } from "@point_of_sale/app/errors/popups/error_popup";
|
||||
const dropPrevious = new concurrency.MutexedDropPrevious(); // Used for queuing reward updates
|
||||
const mutex = new Mutex(); // Used for sequential cache updates
|
||||
|
||||
const COUPON_CACHE_MAX_SIZE = 4096; // Maximum coupon cache size, prevents long run memory issues and (to some extent) invalid data
|
||||
|
||||
function _newRandomRewardCode() {
|
||||
return (Math.random() + 1).toString(36).substring(3);
|
||||
}
|
||||
@@ -80,204 +76,6 @@ function computeFreeQuantity(numberItems, n, m) {
|
||||
return Math.floor(free + adjustment);
|
||||
}
|
||||
|
||||
patch(PosGlobalState.prototype, "pos_loyalty.PosGlobalState", {
|
||||
//@override
|
||||
async _processData(loadedData) {
|
||||
this.couponCache = {};
|
||||
this.partnerId2CouponIds = {};
|
||||
this.rewards = loadedData["loyalty.reward"] || [];
|
||||
|
||||
for (const reward of this.rewards) {
|
||||
reward.all_discount_product_ids = new Set(reward.all_discount_product_ids);
|
||||
}
|
||||
|
||||
await this._super(loadedData);
|
||||
this.productId2ProgramIds = loadedData["product_id_to_program_ids"];
|
||||
this.programs = loadedData["loyalty.program"] || []; //TODO: rename to `loyaltyPrograms` etc
|
||||
this.rules = loadedData["loyalty.rule"] || [];
|
||||
this._loadLoyaltyData();
|
||||
},
|
||||
|
||||
_loadProductProduct(products) {
|
||||
this._super(...arguments);
|
||||
|
||||
for (const reward of this.rewards) {
|
||||
this.compute_discount_product_ids(reward, products);
|
||||
}
|
||||
|
||||
this.rewards = this.rewards.filter(Boolean);
|
||||
},
|
||||
|
||||
compute_discount_product_ids(reward, products) {
|
||||
const reward_product_domain = JSON.parse(reward.reward_product_domain);
|
||||
if (!reward_product_domain) {
|
||||
return;
|
||||
}
|
||||
|
||||
const domain = new Domain(reward_product_domain);
|
||||
|
||||
try {
|
||||
products
|
||||
.filter((product) => domain.contains(product))
|
||||
.forEach((product) => reward.all_discount_product_ids.add(product.id));
|
||||
} catch (error) {
|
||||
if (!(error instanceof InvalidDomainError)) {
|
||||
throw error;
|
||||
}
|
||||
const index = this.rewards.indexOf(reward);
|
||||
if (index != -1) {
|
||||
this.pos.env.services.popup.add(ErrorPopup, {
|
||||
title: _t("A reward could not be loaded"),
|
||||
body: sprintf(
|
||||
_t(
|
||||
'The reward "%s" contain an error in its domain, your domain must be compatible with the PoS client'
|
||||
),
|
||||
this.rewards[index].description
|
||||
),
|
||||
});
|
||||
this.rewards[index] = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
_loadLoyaltyData() {
|
||||
this.program_by_id = {};
|
||||
this.reward_by_id = {};
|
||||
|
||||
for (const program of this.programs) {
|
||||
this.program_by_id[program.id] = program;
|
||||
if (program.date_from) {
|
||||
program.date_from = new Date(program.date_from);
|
||||
}
|
||||
if (program.date_to) {
|
||||
program.date_to = new Date(program.date_to);
|
||||
}
|
||||
program.rules = [];
|
||||
program.rewards = [];
|
||||
}
|
||||
for (const rule of this.rules) {
|
||||
rule.valid_product_ids = new Set(rule.valid_product_ids);
|
||||
rule.program_id = this.program_by_id[rule.program_id[0]];
|
||||
rule.program_id.rules.push(rule);
|
||||
}
|
||||
for (const reward of this.rewards) {
|
||||
this.reward_by_id[reward.id] = reward;
|
||||
reward.program_id = this.program_by_id[reward.program_id[0]];
|
||||
reward.discount_line_product_id = this.db.get_product_by_id(
|
||||
reward.discount_line_product_id[0]
|
||||
);
|
||||
reward.all_discount_product_ids = new Set(reward.all_discount_product_ids);
|
||||
reward.program_id.rewards.push(reward);
|
||||
}
|
||||
},
|
||||
async load_server_data() {
|
||||
await this._super(...arguments);
|
||||
if (this.selectedOrder) {
|
||||
this.selectedOrder._updateRewards();
|
||||
}
|
||||
},
|
||||
set_order(order) {
|
||||
const result = this._super(...arguments);
|
||||
// FIXME - JCB: This is a temporary fix.
|
||||
// When an order is selected, it doesn't always contain the reward lines.
|
||||
// And the list of active programs are not always correct. This is because
|
||||
// of the use of DropPrevious in _updateRewards.
|
||||
if (order) {
|
||||
order._updateRewards();
|
||||
}
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* Fetches `loyalty.card` records from the server and adds/updates them in our cache.
|
||||
*
|
||||
* @param {domain} domain For the search
|
||||
* @param {int} limit Default to 1
|
||||
*/
|
||||
async fetchCoupons(domain, limit = 1) {
|
||||
const result = await this.env.services.orm.searchRead(
|
||||
"loyalty.card",
|
||||
domain,
|
||||
["id", "points", "code", "partner_id", "program_id"],
|
||||
{ limit }
|
||||
);
|
||||
if (Object.keys(this.couponCache).length + result.length > COUPON_CACHE_MAX_SIZE) {
|
||||
this.couponCache = {};
|
||||
this.partnerId2CouponIds = {};
|
||||
// Make sure that the current order has no invalid data.
|
||||
if (this.selectedOrder) {
|
||||
this.selectedOrder.invalidCoupons = true;
|
||||
}
|
||||
}
|
||||
const couponList = [];
|
||||
for (const dbCoupon of result) {
|
||||
const coupon = new PosLoyaltyCard(
|
||||
dbCoupon.code,
|
||||
dbCoupon.id,
|
||||
dbCoupon.program_id[0],
|
||||
dbCoupon.partner_id[0],
|
||||
dbCoupon.points
|
||||
);
|
||||
this.couponCache[coupon.id] = coupon;
|
||||
this.partnerId2CouponIds[coupon.partner_id] =
|
||||
this.partnerId2CouponIds[coupon.partner_id] || new Set();
|
||||
this.partnerId2CouponIds[coupon.partner_id].add(coupon.id);
|
||||
couponList.push(coupon);
|
||||
}
|
||||
return couponList;
|
||||
},
|
||||
/**
|
||||
* Fetches a loyalty card for the given program and partner, put in cache afterwards
|
||||
* if a matching card is found in the cache, that one is used instead.
|
||||
* If no card is found a local only card will be created until the order is validated.
|
||||
*
|
||||
* @param {int} programId
|
||||
* @param {int} partnerId
|
||||
*/
|
||||
async fetchLoyaltyCard(programId, partnerId) {
|
||||
for (const coupon of Object.values(this.couponCache)) {
|
||||
if (coupon.partner_id === partnerId && coupon.program_id === programId) {
|
||||
return coupon;
|
||||
}
|
||||
}
|
||||
const fetchedCoupons = await this.fetchCoupons([
|
||||
["partner_id", "=", partnerId],
|
||||
["program_id", "=", programId],
|
||||
]);
|
||||
const dbCoupon = fetchedCoupons.length > 0 ? fetchedCoupons[0] : null;
|
||||
return dbCoupon || new PosLoyaltyCard(null, null, programId, partnerId, 0);
|
||||
},
|
||||
getLoyaltyCards(partner) {
|
||||
const loyaltyCards = [];
|
||||
if (this.partnerId2CouponIds[partner.id]) {
|
||||
this.partnerId2CouponIds[partner.id].forEach((couponId) =>
|
||||
loyaltyCards.push(this.couponCache[couponId])
|
||||
);
|
||||
}
|
||||
return loyaltyCards;
|
||||
},
|
||||
addPartners(partners) {
|
||||
const result = this._super(partners);
|
||||
// cache the loyalty cards of the partners
|
||||
for (const partner of partners) {
|
||||
for (const [couponId, { code, program_id, points }] of Object.entries(
|
||||
partner.loyalty_cards || {}
|
||||
)) {
|
||||
this.couponCache[couponId] = new PosLoyaltyCard(
|
||||
code,
|
||||
parseInt(couponId, 10),
|
||||
program_id,
|
||||
partner.id,
|
||||
points
|
||||
);
|
||||
this.partnerId2CouponIds[partner.id] =
|
||||
this.partnerId2CouponIds[partner.id] || new Set();
|
||||
this.partnerId2CouponIds[partner.id].add(couponId);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
});
|
||||
|
||||
patch(Orderline.prototype, "pos_loyalty.Orderline", {
|
||||
export_as_JSON() {
|
||||
const result = this._super(...arguments);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(OrderSummary.prototype, "pos_loyalty.OrderSummary", {
|
||||
getLoyaltyPoints() {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
return order.getLoyaltyPoints();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -11,9 +11,9 @@ patch(Orderline.prototype, "pos_loyalty.Orderline", {
|
||||
);
|
||||
},
|
||||
_isGiftCardOrEWalletReward() {
|
||||
const coupon = this.pos.globalState.couponCache[this.props.line.coupon_id];
|
||||
const coupon = this.pos.couponCache[this.props.line.coupon_id];
|
||||
if (coupon) {
|
||||
const program = this.pos.globalState.program_by_id[coupon.program_id];
|
||||
const program = this.pos.program_by_id[coupon.program_id];
|
||||
return (
|
||||
["ewallet", "gift_card"].includes(program.program_type) &&
|
||||
this.props.line.is_reward_line
|
||||
@@ -22,7 +22,7 @@ patch(Orderline.prototype, "pos_loyalty.Orderline", {
|
||||
return false;
|
||||
},
|
||||
_getGiftCardOrEWalletBalance() {
|
||||
const coupon = this.pos.globalState.couponCache[this.props.line.coupon_id];
|
||||
const coupon = this.pos.couponCache[this.props.line.coupon_id];
|
||||
if (coupon) {
|
||||
return this.env.utils.formatCurrency(coupon.balance);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ patch(PartnerLine.prototype, "pos_loyalty.PartnerLine", {
|
||||
this.pos = usePos();
|
||||
},
|
||||
_getLoyaltyPointsRepr(loyaltyCard) {
|
||||
const program = this.pos.globalState.program_by_id[loyaltyCard.program_id];
|
||||
const program = this.pos.program_by_id[loyaltyCard.program_id];
|
||||
if (program.program_type === "ewallet") {
|
||||
return `${program.name}: ${this.env.utils.formatCurrency(loyaltyCard.balance)}`;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ patch(PaymentScreen.prototype, "pos_loyalty.PaymentScreen", {
|
||||
[[], pointChanges, newCodes]
|
||||
);
|
||||
// Payload may contain the points of the concerned coupons to be updated in case of error. (So that rewards can be corrected)
|
||||
const { couponCache } = this.pos.globalState;
|
||||
const { couponCache } = this.pos;
|
||||
if (payload && payload.updated_points) {
|
||||
for (const pointChange of Object.entries(payload.updated_points)) {
|
||||
if (couponCache[pointChange[0]]) {
|
||||
@@ -80,7 +80,7 @@ patch(PaymentScreen.prototype, "pos_loyalty.PaymentScreen", {
|
||||
async _postPushOrderResolve(order, server_ids) {
|
||||
// Compile data for our function
|
||||
const _super = this._super;
|
||||
const { program_by_id, reward_by_id, couponCache } = this.pos.globalState;
|
||||
const { program_by_id, reward_by_id, couponCache } = this.pos;
|
||||
const rewardLines = order._get_reward_lines();
|
||||
const partner = order.get_partner();
|
||||
let couponData = Object.values(order.couponPointChanges).reduce((agg, pe) => {
|
||||
|
||||
@@ -41,7 +41,7 @@ patch(ProductScreen.prototype, "pos_loyalty.ProductScreen", {
|
||||
!selectedLine.manual_reward &&
|
||||
(key === "Backspace" || key === "Delete")
|
||||
) {
|
||||
const reward = this.pos.globalState.reward_by_id[selectedLine.reward_id];
|
||||
const reward = this.pos.reward_by_id[selectedLine.reward_id];
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: this.env._t("Deactivating reward"),
|
||||
body: sprintf(
|
||||
@@ -87,7 +87,7 @@ patch(ProductScreen.prototype, "pos_loyalty.ProductScreen", {
|
||||
}
|
||||
if (selectedLine.is_reward_line && val === "remove") {
|
||||
this.currentOrder.disabledRewards.add(selectedLine.reward_id);
|
||||
const { couponCache } = this.pos.globalState;
|
||||
const { couponCache } = this.pos;
|
||||
const coupon = couponCache[selectedLine.coupon_id];
|
||||
if (
|
||||
coupon &&
|
||||
|
||||
@@ -43,12 +43,12 @@ patch(TicketScreen.prototype, "pos_loyalty.TicketScreen", {
|
||||
);
|
||||
},
|
||||
_isEWalletGiftCard(orderline) {
|
||||
const linkedProgramIds = this.pos.globalState.productId2ProgramIds[orderline.product.id];
|
||||
const linkedProgramIds = this.pos.productId2ProgramIds[orderline.product.id];
|
||||
if (linkedProgramIds) {
|
||||
return linkedProgramIds.length > 0;
|
||||
}
|
||||
if (orderline.is_reward_line) {
|
||||
const reward = this.pos.globalState.reward_by_id[orderline.reward_id];
|
||||
const reward = this.pos.reward_by_id[orderline.reward_id];
|
||||
const program = reward && reward.program_id;
|
||||
if (program && ["gift_card", "ewallet"].includes(program.program_type)) {
|
||||
return true;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<templates id="template" xml:space="preserve">
|
||||
|
||||
<t t-name="point_of_sale.eWalletButton" owl="1">
|
||||
<t t-set="_order" t-value="pos.globalState.get_order()" />
|
||||
<t t-set="_order" t-value="pos.get_order()" />
|
||||
<t t-set="_orderTotal" t-value="_order.get_total_with_tax()" />
|
||||
<t t-set="_eWalletPrograms" t-value="_getEWalletPrograms()" />
|
||||
<t t-set="_eWalletRewards" t-value="_getEWalletRewards(_order)" />
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="pos_loyalty.PartnerLine" t-inherit="point_of_sale.PartnerLine" t-inherit-mode="extension" owl="1">
|
||||
<xpath expr="//td[hasclass('partner-line-balance')]" position="inside">
|
||||
<t t-set="_loyaltyCards" t-value="pos.globalState.getLoyaltyCards(props.partner)" />
|
||||
<t t-set="_loyaltyCards" t-value="pos.getLoyaltyCards(props.partner)" />
|
||||
<t t-foreach="_loyaltyCards" t-as="_loyaltyCard" t-key="_loyaltyCard.id">
|
||||
<div class="pos-right-align">
|
||||
<t t-esc="_getLoyaltyPointsRepr(_loyaltyCard)"/>
|
||||
|
||||
@@ -96,7 +96,7 @@ const lookUpCodeTransaction = {
|
||||
patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
setup() {
|
||||
this._super(...arguments);
|
||||
if (this.pos.globalState.getOnlinePaymentMethods().length !== 0) {
|
||||
if (this.pos.getOnlinePaymentMethods().length !== 0) {
|
||||
useBarcodeReader({
|
||||
credit: this.credit_code_action,
|
||||
});
|
||||
@@ -123,7 +123,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
},
|
||||
_get_swipe_pending_line() {
|
||||
var i = 0;
|
||||
var lines = this.pos.globalState.get_order().get_paymentlines();
|
||||
var lines = this.pos.get_order().get_paymentlines();
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (lines[i].mercury_swipe_pending) {
|
||||
@@ -135,7 +135,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
},
|
||||
_does_credit_payment_line_exist(amount, card_number, card_brand, card_owner_name) {
|
||||
var i = 0;
|
||||
var lines = this.pos.globalState.get_order().get_paymentlines();
|
||||
var lines = this.pos.get_order().get_paymentlines();
|
||||
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (
|
||||
@@ -191,8 +191,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
},
|
||||
// Handler to manage the card reader string
|
||||
credit_code_transaction(parsed_result, old_deferred, retry_nr) {
|
||||
const { globalState } = this.pos.globalState;
|
||||
const order = globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
if (order.get_due(order.selected_paymentline) < 0) {
|
||||
this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Refunds not supported"),
|
||||
@@ -203,11 +202,11 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
return;
|
||||
}
|
||||
|
||||
if (globalState.getOnlinePaymentMethods().length === 0) {
|
||||
if (this.pos.getOnlinePaymentMethods().length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var decodedMagtek = globalState.decodeMagtek(parsed_result.code);
|
||||
var decodedMagtek = this.pos.decodeMagtek(parsed_result.code);
|
||||
|
||||
if (!decodedMagtek) {
|
||||
this.popup.add(ErrorPopup, {
|
||||
@@ -225,7 +224,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
if (swipe_pending_line) {
|
||||
purchase_amount = swipe_pending_line.get_amount();
|
||||
} else {
|
||||
purchase_amount = globalState.get_order().get_due();
|
||||
purchase_amount = this.pos.get_order().get_due();
|
||||
}
|
||||
|
||||
var transaction = {
|
||||
@@ -233,7 +232,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
encrypted_block: decodedMagtek["encrypted_block"],
|
||||
transaction_type: "Credit",
|
||||
transaction_code: "Sale",
|
||||
invoice_no: globalState.get_order().uid.replace(/-/g, ""),
|
||||
invoice_no: this.pos.get_order().uid.replace(/-/g, ""),
|
||||
purchase: purchase_amount,
|
||||
payment_method_id: parsed_result.payment_method_id,
|
||||
};
|
||||
@@ -283,7 +282,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = globalState.decodeMercuryResponse(data);
|
||||
var response = this.pos.decodeMercuryResponse(data);
|
||||
response.payment_method_id = parsed_result.payment_method_id;
|
||||
|
||||
if (response.status === "Approved") {
|
||||
@@ -303,7 +302,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
});
|
||||
} else {
|
||||
// If the payment is approved, add a payment line
|
||||
var order = globalState.get_order();
|
||||
var order = this.pos.get_order();
|
||||
|
||||
if (swipe_pending_line) {
|
||||
order.select_paymentline(swipe_pending_line);
|
||||
@@ -379,7 +378,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
return;
|
||||
},
|
||||
credit_code_action(parsed_result) {
|
||||
var online_payment_methods = this.pos.globalState.getOnlinePaymentMethods();
|
||||
var online_payment_methods = this.pos.getOnlinePaymentMethods();
|
||||
|
||||
if (online_payment_methods.length === 1) {
|
||||
parsed_result.payment_method_id = online_payment_methods[0].item;
|
||||
@@ -408,7 +407,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
}
|
||||
},
|
||||
remove_paymentline_by_ref(line) {
|
||||
this.pos.globalState.get_order().remove_paymentline(line);
|
||||
this.pos.get_order().remove_paymentline(line);
|
||||
this.numberBuffer.reset();
|
||||
},
|
||||
do_reversal(line, is_voidsale, old_deferred, retry_nr) {
|
||||
@@ -467,7 +466,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
return;
|
||||
}
|
||||
|
||||
var response = self.pos.globalState.decodeMercuryResponse(data);
|
||||
var response = self.pos.decodeMercuryResponse(data);
|
||||
|
||||
if (!is_voidsale) {
|
||||
if (response.status != "Approved" || response.message != "REVERSED") {
|
||||
@@ -520,7 +519,7 @@ patch(PaymentScreen.prototype, "pos_mercury.PaymentScreen", {
|
||||
* @override
|
||||
*/
|
||||
addNewPaymentLine(paymentMethod) {
|
||||
const order = this.pos.globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
const res = this._super(...arguments);
|
||||
if (res && paymentMethod.pos_mercury_config_id) {
|
||||
order.selected_paymentline.mercury_swipe_pending = true;
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
/** @odoo-module */
|
||||
|
||||
import { PosGlobalState, Order, Payment } from "@point_of_sale/app/store/models";
|
||||
import { PosStore } from "@point_of_sale/app/store/pos_store";
|
||||
import { Order, Payment } from "@point_of_sale/app/store/models";
|
||||
import { patch } from "@web/core/utils/patch";
|
||||
|
||||
patch(PosGlobalState.prototype, "pos_mercury.PosGlobalState", {
|
||||
patch(PosStore.prototype, "pos_mercury.PosStore", {
|
||||
getOnlinePaymentMethods() {
|
||||
var online_payment_methods = [];
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export class EditableTable extends Component {
|
||||
}
|
||||
|
||||
onMoveStart() {
|
||||
if (this.pos.globalState.floorPlanStyle == "kanban") {
|
||||
if (this.pos.floorPlanStyle == "kanban") {
|
||||
return;
|
||||
}
|
||||
this.startTable = { ...this.props.table };
|
||||
@@ -60,7 +60,7 @@ export class EditableTable extends Component {
|
||||
}
|
||||
|
||||
onMove({ dx, dy }) {
|
||||
if (this.pos.globalState.floorPlanStyle == "kanban") {
|
||||
if (this.pos.floorPlanStyle == "kanban") {
|
||||
return;
|
||||
}
|
||||
const { minX, minY, maxX, maxY } = getLimits(this.root.el, this.props.limit.el);
|
||||
@@ -76,7 +76,7 @@ export class EditableTable extends Component {
|
||||
}
|
||||
|
||||
onResizeHandleMove([moveX, moveY], { dx, dy }) {
|
||||
if (this.pos.globalState.floorPlanStyle == "kanban") {
|
||||
if (this.pos.floorPlanStyle == "kanban") {
|
||||
return;
|
||||
}
|
||||
// Working with min/max x and y makes constraints much easier to apply uniformly
|
||||
@@ -128,7 +128,7 @@ export class EditableTable extends Component {
|
||||
|
||||
_setElementStyle() {
|
||||
const table = this.props.table;
|
||||
if (this.pos.globalState.floorPlanStyle == "kanban") {
|
||||
if (this.pos.floorPlanStyle == "kanban") {
|
||||
const floor = table.floor;
|
||||
const index = floor.tables.indexOf(table);
|
||||
const minWidth = 100 + 20;
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<span class="table-seats">
|
||||
<t t-esc="props.table.seats" />
|
||||
</span>
|
||||
<t t-if="pos.globalState.floorPlanStyle != 'kanban'" t-foreach="handles" t-as="handle" t-key="handle">
|
||||
<t t-if="pos.floorPlanStyle != 'kanban'" t-foreach="handles" t-as="handle" t-key="handle">
|
||||
<span class="table-handle" t-ref="{{handle}}" t-att-style="computeHandleStyle(handle)"/>
|
||||
</t>
|
||||
</div>
|
||||
|
||||
@@ -35,7 +35,7 @@ export class FloorScreen extends Component {
|
||||
this.pos = usePos();
|
||||
this.popup = useService("popup");
|
||||
this.orm = useService("orm");
|
||||
const floor = this.props.floor || this.pos.globalState.floors[0];
|
||||
const floor = this.props.floor || this.pos.floors[0];
|
||||
this.state = useState({
|
||||
selectedFloorId: floor ? floor.id : null,
|
||||
selectedTableIds: [],
|
||||
@@ -44,7 +44,7 @@ export class FloorScreen extends Component {
|
||||
isColorPicker: false,
|
||||
});
|
||||
const ui = useState(useService("ui"));
|
||||
this.pos.globalState.floorPlanStyle = ui.isSmall ? "kanban" : "default";
|
||||
this.pos.floorPlanStyle = ui.isSmall ? "kanban" : "default";
|
||||
this.floorMapRef = useRef("floor-map-ref");
|
||||
this.addFloorRef = useRef("add-floor-ref");
|
||||
this.map = useRef("map");
|
||||
@@ -56,7 +56,7 @@ export class FloorScreen extends Component {
|
||||
onPatched() {
|
||||
this.floorMapRef.el.style.background = this.state.floorBackground;
|
||||
this.addFloorRef.el.style.background = this.state.floorBackground;
|
||||
if (!this.pos.globalState.isEditMode && this.pos.globalState.floors.length > 0) {
|
||||
if (!this.pos.isEditMode && this.pos.floors.length > 0) {
|
||||
this.addFloorRef.el.style.display = "none";
|
||||
} else {
|
||||
this.addFloorRef.el.style.display = "initial";
|
||||
@@ -64,9 +64,9 @@ export class FloorScreen extends Component {
|
||||
this.state.floorMapScrollTop = this.floorMapRef.el.getBoundingClientRect().top;
|
||||
}
|
||||
async onWillStart() {
|
||||
const table = this.pos.globalState.table;
|
||||
const table = this.pos.table;
|
||||
if (table) {
|
||||
const orders = this.pos.globalState.get_order_list();
|
||||
const orders = this.pos.get_order_list();
|
||||
const tableOrders = orders.filter(
|
||||
(order) => order.tableId === table.id && !order.finalized
|
||||
);
|
||||
@@ -84,13 +84,13 @@ export class FloorScreen extends Component {
|
||||
table.changes_count = qtyChange.changed;
|
||||
table.skip_changes = qtyChange.skipped;
|
||||
}
|
||||
await this.pos.globalState.unsetTable();
|
||||
await this.pos.unsetTable();
|
||||
}
|
||||
onMounted() {
|
||||
this.pos.openCashControl();
|
||||
this.floorMapRef.el.style.background = this.state.floorBackground;
|
||||
this.addFloorRef.el.style.background = this.state.floorBackground;
|
||||
if (!this.pos.globalState.isEditMode && this.pos.globalState.floors.length > 0) {
|
||||
if (!this.pos.isEditMode && this.pos.floors.length > 0) {
|
||||
this.addFloorRef.el.style.display = "none";
|
||||
} else {
|
||||
this.addFloorRef.el.style.display = "initial";
|
||||
@@ -272,14 +272,14 @@ export class FloorScreen extends Component {
|
||||
delete tableCopy.floor;
|
||||
const tableId = await this.orm.call("restaurant.table", "create_from_ui", [tableCopy]);
|
||||
table.id = tableId;
|
||||
this.pos.globalState.tables_by_id[tableId] = table;
|
||||
this.pos.tables_by_id[tableId] = table;
|
||||
}
|
||||
async _renameFloor(floorId, newName) {
|
||||
await this.orm.call("restaurant.floor", "rename_floor", [floorId, newName]);
|
||||
}
|
||||
get activeFloor() {
|
||||
return this.state.selectedFloorId
|
||||
? this.pos.globalState.floors_by_id[this.state.selectedFloorId]
|
||||
? this.pos.floors_by_id[this.state.selectedFloorId]
|
||||
: null;
|
||||
}
|
||||
get activeTables() {
|
||||
@@ -291,12 +291,12 @@ export class FloorScreen extends Component {
|
||||
get selectedTables() {
|
||||
const tables = [];
|
||||
this.state.selectedTableIds.forEach((id) => {
|
||||
tables.push(this.pos.globalState.tables_by_id[id]);
|
||||
tables.push(this.pos.tables_by_id[id]);
|
||||
});
|
||||
return tables;
|
||||
}
|
||||
get nbrFloors() {
|
||||
return this.pos.globalState.floors.length;
|
||||
return this.pos.floors.length;
|
||||
}
|
||||
movePinch(hypot) {
|
||||
const delta = hypot / this.scalehypot;
|
||||
@@ -324,8 +324,8 @@ export class FloorScreen extends Component {
|
||||
this.state.selectedTableIds = [];
|
||||
}
|
||||
toggleEditMode() {
|
||||
this.pos.globalState.toggleEditMode();
|
||||
if (!this.pos.globalState.isEditMode && this.pos.globalState.floors.length > 0) {
|
||||
this.pos.toggleEditMode();
|
||||
if (!this.pos.isEditMode && this.pos.floors.length > 0) {
|
||||
this.addFloorRef.el.style.display = "none";
|
||||
} else {
|
||||
this.addFloorRef.el.style.display = "initial";
|
||||
@@ -333,8 +333,7 @@ export class FloorScreen extends Component {
|
||||
this.state.selectedTableIds = [];
|
||||
}
|
||||
async onSelectTable(table, ev) {
|
||||
const { globalState } = this.pos;
|
||||
if (globalState.isEditMode) {
|
||||
if (this.pos.isEditMode) {
|
||||
if (ev.ctrlKey || ev.metaKey) {
|
||||
this.state.selectedTableIds.push(table.id);
|
||||
} else {
|
||||
@@ -342,11 +341,11 @@ export class FloorScreen extends Component {
|
||||
this.state.selectedTableIds.push(table.id);
|
||||
}
|
||||
} else {
|
||||
if (globalState.orderToTransfer) {
|
||||
await globalState.transferTable(table);
|
||||
if (this.pos.orderToTransfer) {
|
||||
await this.pos.transferTable(table);
|
||||
} else {
|
||||
try {
|
||||
await globalState.setTable(table);
|
||||
await this.pos.setTable(table);
|
||||
} catch (e) {
|
||||
if (!(e instanceof ConnectionLostError)) {
|
||||
throw e;
|
||||
@@ -355,7 +354,7 @@ export class FloorScreen extends Component {
|
||||
Promise.reject(e);
|
||||
}
|
||||
}
|
||||
const order = globalState.get_order();
|
||||
const order = this.pos.get_order();
|
||||
this.pos.showScreen(order.get_screen_data().name);
|
||||
}
|
||||
}
|
||||
@@ -369,16 +368,15 @@ export class FloorScreen extends Component {
|
||||
if (!confirmed) {
|
||||
return;
|
||||
}
|
||||
const { globalState } = this.pos;
|
||||
const floor = await this.orm.call("restaurant.floor", "create_from_ui", [
|
||||
newName,
|
||||
"#ACADAD",
|
||||
globalState.config.id,
|
||||
this.pos.config.id,
|
||||
]);
|
||||
globalState.floors_by_id[floor.id] = floor;
|
||||
globalState.floors.push(floor);
|
||||
this.pos.floors_by_id[floor.id] = floor;
|
||||
this.pos.floors.push(floor);
|
||||
this.selectFloor(floor);
|
||||
globalState.isEditMode = true;
|
||||
this.pos.isEditMode = true;
|
||||
}
|
||||
async createTable() {
|
||||
const newTable = await this._createTableHelper();
|
||||
@@ -389,17 +387,16 @@ export class FloorScreen extends Component {
|
||||
}
|
||||
async duplicateTableOrFloor() {
|
||||
if (this.selectedTables.length == 0) {
|
||||
const { globalState } = this.pos;
|
||||
const floor = this.activeFloor;
|
||||
const tables = this.activeFloor.tables;
|
||||
const newFloorName = floor.name + " (copy)";
|
||||
const newFloor = await this.orm.call("restaurant.floor", "create_from_ui", [
|
||||
newFloorName,
|
||||
floor.background_color,
|
||||
globalState.config.id,
|
||||
this.pos.config.id,
|
||||
]);
|
||||
globalState.floors_by_id[newFloor.id] = newFloor;
|
||||
globalState.floors.push(newFloor);
|
||||
this.pos.floors_by_id[newFloor.id] = newFloor;
|
||||
this.pos.floors.push(newFloor);
|
||||
this.selectFloor(newFloor);
|
||||
for (const table of tables) {
|
||||
await this._createTableHelper(table, true);
|
||||
@@ -506,7 +503,6 @@ export class FloorScreen extends Component {
|
||||
this.state.isColorPicker = !this.state.isColorPicker;
|
||||
}
|
||||
async deleteFloorOrTable() {
|
||||
const { globalState } = this.pos;
|
||||
if (this.selectedTables.length == 0) {
|
||||
const { confirmed } = await this.popup.add(ConfirmPopup, {
|
||||
title: `Removing floor ${this.activeFloor.name}`,
|
||||
@@ -521,28 +517,28 @@ export class FloorScreen extends Component {
|
||||
const originalSelectedFloorId = this.activeFloor.id;
|
||||
await this.orm.call("restaurant.floor", "deactivate_floor", [
|
||||
originalSelectedFloorId,
|
||||
globalState.pos_session.id,
|
||||
this.pos.pos_session.id,
|
||||
]);
|
||||
const floor = globalState.floors_by_id[originalSelectedFloorId];
|
||||
const orderList = [...globalState.get_order_list()];
|
||||
const floor = this.pos.floors_by_id[originalSelectedFloorId];
|
||||
const orderList = [...this.pos.get_order_list()];
|
||||
for (const order of orderList) {
|
||||
if (floor.table_ids.includes(order.tableId)) {
|
||||
globalState.removeOrder(order, false);
|
||||
this.pos.removeOrder(order, false);
|
||||
}
|
||||
}
|
||||
floor.table_ids.forEach((tableId) => {
|
||||
delete globalState.tables_by_id[tableId];
|
||||
delete this.pos.tables_by_id[tableId];
|
||||
});
|
||||
delete globalState.floors_by_id[originalSelectedFloorId];
|
||||
globalState.floors = globalState.floors.filter(
|
||||
delete this.pos.floors_by_id[originalSelectedFloorId];
|
||||
this.pos.floors = this.pos.floors.filter(
|
||||
(floor) => floor.id != originalSelectedFloorId
|
||||
);
|
||||
globalState.TICKET_SCREEN_STATE.syncedOrders.cache = {};
|
||||
if (globalState.floors.length > 0) {
|
||||
this.selectFloor(globalState.floors[0]);
|
||||
this.pos.TICKET_SCREEN_STATE.syncedOrders.cache = {};
|
||||
if (this.pos.floors.length > 0) {
|
||||
this.selectFloor(this.pos.floors[0]);
|
||||
} else {
|
||||
globalState.isEditMode = false;
|
||||
globalState.floorPlanStyle = "default";
|
||||
this.pos.isEditMode = false;
|
||||
this.pos.floorPlanStyle = "default";
|
||||
this.state.floorBackground = null;
|
||||
}
|
||||
return;
|
||||
@@ -561,17 +557,17 @@ export class FloorScreen extends Component {
|
||||
]);
|
||||
if (!response) {
|
||||
//remove order not send to server
|
||||
for (const order of globalState.get_order_list()) {
|
||||
for (const order of this.pos.get_order_list()) {
|
||||
if (order.tableId == id) {
|
||||
globalState.removeOrder(order, false);
|
||||
this.pos.removeOrder(order, false);
|
||||
}
|
||||
}
|
||||
globalState.tables_by_id[id].active = false;
|
||||
this.pos.tables_by_id[id].active = false;
|
||||
await this.orm.call("restaurant.table", "create_from_ui", [
|
||||
{ active: false, id: id },
|
||||
]);
|
||||
this.activeFloor.tables = this.activeTables.filter((table) => table.id !== id);
|
||||
delete globalState.tables_by_id[id];
|
||||
delete this.pos.tables_by_id[id];
|
||||
} else {
|
||||
await this.popup.add(ErrorPopup, {
|
||||
title: this.env._t("Delete Error"),
|
||||
@@ -593,7 +589,7 @@ export class FloorScreen extends Component {
|
||||
if (equalsCheck(this.state.selectedTableIds, originalSelectedTableIds)) {
|
||||
this.state.selectedTableIds = [];
|
||||
}
|
||||
globalState.TICKET_SCREEN_STATE.syncedOrders.cache = {};
|
||||
this.pos.TICKET_SCREEN_STATE.syncedOrders.cache = {};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
<t t-name="pos_restaurant.FloorScreen" owl="1">
|
||||
<div class="floor-screen screen">
|
||||
<EditBar t-if="pos.globalState.isEditMode" selectedTables="selectedTables" nbrFloors="nbrFloors"
|
||||
<EditBar t-if="pos.isEditMode" selectedTables="selectedTables" nbrFloors="nbrFloors"
|
||||
floorMapScrollTop="state.floorMapScrollTop" isColorPicker="state.isColorPicker" toggleColorPicker.bind="toggleColorPicker"
|
||||
createTable.bind="createTable" duplicateTableOrFloor.bind="duplicateTableOrFloor" renameTable.bind="renameTable"
|
||||
changeSeatsNum.bind="changeSeatsNum" changeToCircle.bind="changeToCircle" changeToSquare.bind="changeToSquare"
|
||||
@@ -11,7 +11,7 @@
|
||||
toggleEditMode.bind="toggleEditMode"
|
||||
/>
|
||||
<div class="floor-selector">
|
||||
<t t-foreach="pos.globalState.floors" t-as="floor" t-key="floor.id">
|
||||
<t t-foreach="pos.floors" t-as="floor" t-key="floor.id">
|
||||
<span class="button button-floor" t-att-class="{ active: floor.id === state.selectedFloorId }" t-on-click="() => this.selectFloor(floor)">
|
||||
<t t-esc="floor.name" />
|
||||
</span>
|
||||
@@ -29,7 +29,7 @@
|
||||
class="floor-map"
|
||||
t-ref="floor-map-ref"
|
||||
>
|
||||
<t t-if="pos.globalState.floors.length > 0">
|
||||
<t t-if="pos.floors.length > 0">
|
||||
<div t-if="isFloorEmpty" class="empty-floor" t-ref="map">
|
||||
<span>No tables available,<br/>ADD your first table</span>
|
||||
</div>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user