[REF] point_of_sale,*: remove use of legacyEnv in popups

*: l10n_fr_pos_cert, pos_sale_product_configurator

This is a continuation of the effort of making pos addons independent
from legacy web modules. In this commit, the popups are now completely
independent from the legacy environment. `env.pos` inside each popup
is no longer pointing to the instance of `PosGlobalState` (`globalState`).
To access the `globalState` inside each popup, we have to read it from
the `pos` service (via the `usePos` hook) which is done in this commit.

closes odoo/odoo#116307

Related: odoo/enterprise#39271
Signed-off-by: Samuel Degueldre <sad@odoo.com>
This commit is contained in:
Joseph Caburnay
2023-04-04 13:35:06 +02:00
parent 66a99f4743
commit 40ac299c1d
16 changed files with 70 additions and 62 deletions
@@ -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.env.pos.is_french_country() && this.env.pos.pos_session.start_at) {
if (this.pos.globalState.is_french_country() && this.pos.globalState.pos_session.start_at) {
const now = Date.now();
const limitDate = new Date(this.env.pos.pos_session.start_at);
const limitDate = new Date(this.pos.globalState.pos_session.start_at);
limitDate.setDate(limitDate.getDate() + 1);
isOutdated = limitDate < now;
}
@@ -6,6 +6,7 @@ import { renderToString } from "@web/core/utils/render";
import { useAutofocus, useService } from "@web/core/utils/hooks";
import { parseFloat, InvalidNumberError } from "@web/views/fields/parsers";
import { useState } from "@odoo/owl";
import { usePos } from "@point_of_sale/app/pos_hook";
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
@@ -18,6 +19,7 @@ export class CashMovePopup extends AbstractAwaitablePopup {
this.notification = useService("pos_notification");
this.popup = useService("popup");
this.orm = useService("orm");
this.pos = usePos();
this.hardwareProxy = useService("hardware_proxy");
this.state = useState({
/** @type {'in'|'out'} */
@@ -43,7 +45,7 @@ export class CashMovePopup extends AbstractAwaitablePopup {
this.state.errorMessage = this.env._t("Insert a positive amount");
return;
}
const formattedAmount = this.env.pos.format_currency(amount);
const formattedAmount = this.pos.globalState.format_currency(amount);
if (!amount) {
this.notification.add(
sprintf(_t("Cash in/out of %s is ignored."), formattedAmount),
@@ -57,7 +59,7 @@ 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.env.pos.pos_session.id],
[this.pos.globalState.pos_session.id],
type,
amount,
reason,
@@ -71,8 +73,8 @@ export class CashMovePopup extends AbstractAwaitablePopup {
amount,
translatedType,
formattedAmount,
cashier: this.env.pos.get_cashier(),
company: this.env.pos.company,
cashier: this.pos.globalState.get_cashier(),
company: this.pos.globalState.company,
},
});
const printResult = await this.hardwareProxy.printer.print_receipt(renderedReceipt);
@@ -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="env.pos.currency.symbol.length > 1">
<span class="left-currency" t-esc="env.pos.currency.symbol" />
<t t-if="pos.globalState.currency.symbol.length > 1">
<span class="left-currency" t-esc="pos.globalState.currency.symbol" />
</t>
<t t-else="">
<span class="currency" t-esc="env.pos.currency.symbol" />
<span class="currency" t-esc="pos.globalState.currency.symbol" />
</t>
</div>
</div>
@@ -2,13 +2,9 @@
import { Component, reactive } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { usePos } from "@point_of_sale/app/pos_hook";
export class PopupContainer extends Component {
static template = "point_of_sale.PopupContainer";
setup() {
// FIXME POSREF: remove this when Chrome uses the new env
this.__owl__.childEnv = usePos().legacyEnv;
}
}
// FIXME POSREF: probably should use the main dialog service from web long term.
@@ -2,6 +2,7 @@
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { useService } from "@web/core/utils/hooks";
import { usePos } from "@point_of_sale/app/pos_hook";
import { MoneyDetailsPopup } from "./MoneyDetailsPopup";
import { useState } from "@odoo/owl";
@@ -13,19 +14,20 @@ export class CashOpeningPopup extends AbstractAwaitablePopup {
super.setup();
this.manualInputCashCount = null;
this.moneyDetails = null;
this.pos = usePos();
this.state = useState({
notes: "",
openingCash: this.env.pos.pos_session.cash_register_balance_start || 0,
openingCash: this.pos.globalState.pos_session.cash_register_balance_start || 0,
});
this.popup = useService("popup");
this.orm = useService("orm");
}
//@override
async confirm() {
this.env.pos.pos_session.cash_register_balance_start = this.state.openingCash;
this.env.pos.pos_session.state = "opened";
this.pos.globalState.pos_session.cash_register_balance_start = this.state.openingCash;
this.pos.globalState.pos_session.state = "opened";
this.orm.call("pos.session", "set_cashbox_pos", [
this.env.pos.pos_session.id,
this.pos.globalState.pos_session.id,
this.state.openingCash,
this.state.notes,
]);
@@ -11,6 +11,7 @@ import { useState } from "@odoo/owl";
import { ConnectionLostError } from "@web/core/network/rpc_service";
import { identifyError } from "@point_of_sale/app/error_handlers/error_handlers";
import { _t } from "@web/core/l10n/translation";
import { usePos } from "@point_of_sale/app/pos_hook";
export class ClosePosPopup extends AbstractAwaitablePopup {
static components = { SaleDetailsButton };
@@ -18,12 +19,13 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
setup() {
super.setup();
this.pos = usePos();
this.popup = useService("popup");
this.pos = useService("pos");
this.orm = useService("orm");
this.hardwareProxy = useService("hardware_proxy");
this.legacyActionManager = useService("legacy_action_manager");
this.manualInputCashCount = false;
this.cashControl = this.env.pos.config.cash_control;
this.cashControl = this.pos.globalState.config.cash_control;
this.closeSessionClicked = false;
this.moneyDetails = null;
Object.assign(this, this.props.info);
@@ -54,7 +56,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
"The maximum difference allowed is %s.\n\
Please contact your manager to accept the closing difference."
),
this.env.pos.format_currency(this.amountAuthorizedDiff)
this.pos.globalState.format_currency(this.amountAuthorizedDiff)
),
confirmText: this.env._t("OK"),
});
@@ -77,7 +79,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
const { total, moneyDetailsNotes, moneyDetails } = payload;
this.state.payments[this.defaultCashDetails.id].counted = total;
this.state.payments[this.defaultCashDetails.id].difference =
this.env.pos.round_decimals_currency(
this.pos.globalState.round_decimals_currency(
this.state.payments[[this.defaultCashDetails.id]].counted -
this.defaultCashDetails.amount
);
@@ -89,9 +91,9 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
}
}
async downloadSalesReport() {
await this.env.legacyActionManager.do_action("point_of_sale.sale_details_report", {
await this.legacyActionManager.do_action("point_of_sale.sale_details_report", {
additional_context: {
active_ids: [this.env.pos.pos_session.id],
active_ids: [this.pos.globalState.pos_session.id],
},
});
}
@@ -105,7 +107,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
} else {
expectedAmount = this.otherPaymentMethods.find((pm) => paymentId === pm.id).amount;
}
this.state.payments[paymentId].difference = this.env.pos.round_decimals_currency(
this.state.payments[paymentId].difference = this.pos.globalState.round_decimals_currency(
this.state.payments[paymentId].counted - expectedAmount
);
}
@@ -129,12 +131,12 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
if (!this.closeSessionClicked) {
this.closeSessionClicked = true;
if (this.env.pos.config.cashControl) {
if (this.pos.globalState.config.cashControl) {
const response = await this.orm.call(
"pos.session",
"post_closing_cash_details"[this.env.pos.pos_session.id],
"post_closing_cash_details"[this.pos.globalState.pos_session.id],
{
counted_cash: this.env.pos.config.cashControl
counted_cash: this.pos.globalState.config.cashControl
? this.state.payments[this.defaultCashDetails.id].counted
: 0,
}
@@ -147,7 +149,7 @@ export class ClosePosPopup extends AbstractAwaitablePopup {
try {
await this.orm.call("pos.session", "update_closing_control_state_session", [
this.env.pos.pos_session.id,
this.pos.globalState.pos_session.id,
this.state.notes,
]);
} catch (error) {
@@ -168,7 +170,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.env.pos.pos_session.id,
this.pos.globalState.pos_session.id,
bankPaymentMethodDiffPairs,
]);
if (!response.successful) {
@@ -2,7 +2,7 @@
import { ErrorPopup } from "@point_of_sale/js/Popups/ErrorPopup";
import { _lt } from "@web/core/l10n/translation";
import { useService } from "@web/core/utils/hooks";
import { usePos } from "@point_of_sale/app/pos_hook";
// formerly ErrorTracebackPopupWidget
export class ErrorTracebackPopup extends ErrorPopup {
@@ -18,7 +18,7 @@ export class ErrorTracebackPopup extends ErrorPopup {
};
setup() {
this.pos = useService("pos");
this.pos = usePos();
}
get tracebackUrl() {
@@ -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.env.pos.company.email;
const address = this.pos.globalState.company.email;
const subject = this.env._t("IMPORTANT: Bug Report From Odoo Point Of Sale");
window.open(
"mailto:" +
@@ -3,6 +3,7 @@
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { useState } from "@odoo/owl";
import { CurrencyAmount } from "../Misc/CurrencyAmount";
import { usePos } from "@point_of_sale/app/pos_hook";
export class MoneyDetailsPopup extends AbstractAwaitablePopup {
static components = { CurrencyAmount };
@@ -10,11 +11,12 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
setup() {
super.setup();
this.currency = this.env.pos.currency;
this.pos = usePos();
this.currency = this.pos.globalState.currency;
this.state = useState({
moneyDetails: this.props.moneyDetails
? { ...this.props.moneyDetails }
: Object.fromEntries(this.env.pos.bills.map((bill) => [bill.value, 0])),
: Object.fromEntries(this.pos.globalState.bills.map((bill) => [bill.value, 0])),
total: this.props.total ? this.props.total : 0,
});
}
@@ -34,16 +36,16 @@ export class MoneyDetailsPopup extends AbstractAwaitablePopup {
(total, money) => total + money[0] * money[1],
0
);
this.state.total = this.env.pos.round_decimals_currency(total);
this.state.total = this.pos.globalState.round_decimals_currency(total);
}
//@override
async getPayload() {
let moneyDetailsNotes = this.state.total ? "Money details: \n" : null;
this.env.pos.bills.forEach((bill) => {
this.pos.globalState.bills.forEach((bill) => {
if (this.state.moneyDetails[bill.value]) {
moneyDetailsNotes += ` - ${
this.state.moneyDetails[bill.value]
} x ${this.env.pos.format_currency(bill.value)}\n`;
} x ${this.pos.globalState.format_currency(bill.value)}\n`;
}
});
return {
@@ -5,6 +5,7 @@ var _t = core._t;
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { useService } from "@web/core/utils/hooks";
import { useState } from "@odoo/owl";
import { localization } from "@web/core/l10n/localization";
export class NumberPopup extends AbstractAwaitablePopup {
static template = "NumberPopup";
@@ -45,7 +46,7 @@ export class NumberPopup extends AbstractAwaitablePopup {
});
}
get decimalSeparator() {
return this.env._t.database.parameters.decimal_point;
return localization.decimalPoint;
}
get inputBuffer() {
if (this.state.buffer === null) {
@@ -1,12 +1,13 @@
/** @odoo-module */
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { Component, useRef, useState, useSubEnv } from "@odoo/owl";
import { usePos } from "@point_of_sale/app/pos_hook";
export class BaseProductAttribute extends Component {
setup() {
super.setup();
this.pos = usePos();
this.env.attribute_components.push(this);
this.attribute = this.props.attribute;
this.values = this.attribute.values;
this.state = useState({
@@ -1,6 +1,7 @@
/** @odoo-module */
import { AbstractAwaitablePopup } from "@point_of_sale/js/Popups/AbstractAwaitablePopup";
import { usePos } from "@point_of_sale/app/pos_hook";
/**
* Props:
@@ -14,17 +15,18 @@ export class ProductInfoPopup extends AbstractAwaitablePopup {
setup() {
super.setup();
this.pos = usePos();
Object.assign(this, this.props.info);
}
searchProduct(productName) {
this.env.pos.setSelectedCategoryId(0);
this.env.pos.searchProductWord = productName;
this.pos.globalState.setSelectedCategoryId(0);
this.pos.globalState.searchProductWord = productName;
this.cancel();
}
_hasMarginsCostsAccessRights() {
const isAccessibleToEveryUser =
this.env.pos.config.is_margins_costs_accessible_to_every_user;
const isCashierManager = this.env.pos.get_cashier().role === "manager";
this.pos.globalState.config.is_margins_costs_accessible_to_every_user;
const isCashierManager = this.pos.globalState.get_cashier().role === "manager";
return isAccessibleToEveryUser || isCashierManager;
}
}
@@ -7,7 +7,7 @@
<div class="title">Closing Session</div>
<div class="total-orders">
Total <t t-esc="ordersDetails.quantity"/> orders:
<span class="amount" t-esc="env.pos.format_currency(ordersDetails.amount)"/>
<span class="amount" t-esc="pos.globalState.format_currency(ordersDetails.amount)"/>
</div>
</header>
<main class="body">
@@ -25,20 +25,20 @@
<tbody>
<tr>
<td t-esc="defaultCashDetails.name"/>
<td t-esc="env.pos.format_currency(defaultCashDetails.amount)"/>
<td t-esc="pos.globalState.format_currency(defaultCashDetails.amount)"/>
<td class="flex" t-on-input="() => this.handleInputChange(defaultCashDetails.id)">
<input class="pos-input" type="number" t-model.number="state.payments[defaultCashDetails.id].counted"/>
<div class="button icon" t-on-click="openDetailsPopup">
<i class="fa fa-calculator" role="img" title="Open the money details popup"/>
</div>
</td>
<td t-esc="env.pos.format_currency(state.payments[defaultCashDetails.id].difference)" t-att-class="{'warning': state.payments[defaultCashDetails.id].difference}"/>
<td t-esc="pos.globalState.format_currency(state.payments[defaultCashDetails.id].difference)" t-att-class="{'warning': state.payments[defaultCashDetails.id].difference}"/>
</tr>
</tbody>
<tbody class="cash-overview">
<tr>
<td>Opening</td>
<td t-esc="env.pos.format_currency(defaultCashDetails.opening)"/>
<td t-esc="pos.globalState.format_currency(defaultCashDetails.opening)"/>
</tr>
<tr t-foreach="defaultCashDetails.moves" t-as="move" t-key="move_index">
<td>
@@ -47,7 +47,7 @@
<t t-esc="move.name"/>
</div>
</td>
<td t-esc="env.pos.format_currency(Math.abs(move.amount))"/>
<td t-esc="pos.globalState.format_currency(Math.abs(move.amount))"/>
</tr>
<tr t-if="defaultCashDetails.payment_amount">
<td>
@@ -56,17 +56,17 @@
Payments in <t t-esc="defaultCashDetails.name"/>
</div>
</td>
<td t-esc="env.pos.format_currency(Math.abs(defaultCashDetails.payment_amount))"/>
<td t-esc="pos.globalState.format_currency(Math.abs(defaultCashDetails.payment_amount))"/>
</tr>
</tbody>
</t>
<tbody t-if="otherPaymentMethods.length &gt; 0">
<tr t-foreach="otherPaymentMethods" t-as="pm" t-key="pm.id">
<td t-esc="pm.name"/>
<td t-esc="env.pos.format_currency(pm.amount)"/>
<td t-esc="pos.globalState.format_currency(pm.amount)"/>
<t t-set="_showDiff" t-value="_getShowDiff(pm)" />
<td t-if="_showDiff" t-on-input="() => this.handleInputChange(pm.id)"><input class="pos-input" type="number" t-model.number="state.payments[pm.id].counted"/></td>
<td t-if="_showDiff" t-esc="env.pos.format_currency(state.payments[pm.id].difference)" t-att-class="{'warning': state.payments[pm.id].difference}"/>
<td t-if="_showDiff" t-esc="pos.globalState.format_currency(state.payments[pm.id].difference)" t-att-class="{'warning': state.payments[pm.id].difference}"/>
</tr>
</tbody>
</table>
@@ -18,7 +18,7 @@
</div>
<div class="total-section">
<span>Total </span>
<CurrencyAmount currency="currency" amount="env.pos.format_currency_no_symbol(state.total)"/>
<CurrencyAmount currency="currency" amount="pos.globalState.format_currency_no_symbol(state.total)"/>
</div>
</main>
<footer class="footer footer-flex">
@@ -39,7 +39,7 @@
</div>
<div t-if="value.price_extra" class="price-extra-cell">
<span class="price_extra">
+ <t t-esc="env.pos.format_currency(value.price_extra)"/>
+ <t t-esc="pos.globalState.format_currency(value.price_extra)"/>
</span>
</div>
<div t-if="value.id == state.selected_value &amp;&amp; value.is_custom" class="custom-value-cell">
@@ -59,7 +59,7 @@
<t t-set="is_custom" t-value="is_custom || (value.is_custom &amp;&amp; value.id == state.selected_value)"/>
<t t-esc="value.name"/>
<t t-if="value.price_extra">
+ <t t-esc="env.pos.format_currency(value.price_extra)"/>
+ <t t-esc="pos.globalState.format_currency(value.price_extra)"/>
</t>
</option>
</select>
@@ -12,9 +12,9 @@
<span><t t-if="props.product.default_code" t-esc="props.product.default_code"/> <t t-if="props.product.default_code and props.product.barcode"> - </t> <t t-if="props.product.barcode" t-esc="props.product.barcode"/></span>
</div>
<div class="column flex-end">
<span t-esc="env.pos.format_currency(productInfo.all_prices.price_with_tax)" class="global-info-title" />
<span t-esc="pos.globalState.format_currency(productInfo.all_prices.price_with_tax)" class="global-info-title" />
<t t-foreach="productInfo.all_prices.tax_details" t-as="tax" t-key="tax.name">
<div><t t-esc="tax.name"/>: <t t-esc="env.pos.format_currency(tax.amount)"/></div>
<div><t t-esc="tax.name"/>: <t t-esc="pos.globalState.format_currency(tax.amount)"/></div>
</t>
</div>
</div>
@@ -27,7 +27,7 @@
<table>
<tr>
<td>Price excl. VAT:</td>
<td><t t-esc="env.pos.format_currency(productInfo.all_prices.price_without_tax)"/></td>
<td><t t-esc="pos.globalState.format_currency(productInfo.all_prices.price_without_tax)"/></td>
</tr>
<tr t-if="_hasMarginsCostsAccessRights()">
<td>Cost:</td>
@@ -42,7 +42,7 @@
<t t-foreach="productInfo.pricelists" t-as="pricelist" t-key="pricelist.name">
<tr>
<td t-esc="pricelist.name"/>
<td t-esc="env.pos.format_currency(pricelist.price)"/>
<td t-esc="pos.globalState.format_currency(pricelist.price)"/>
</tr>
</t>
</table>
@@ -50,7 +50,7 @@
</div>
<div class="section-inventory" t-if="productInfo.warehouses.length > 0">
<div class="section-title">
<span>Inventory <t t-if="env.pos.pos_session.update_stock_at_closing">(as of opening)</t></span>
<span>Inventory <t t-if="pos.globalState.pos_session.update_stock_at_closing">(as of opening)</t></span>
<div class="section-title-line"></div>
</div>
<div class="section-inventory-body">
@@ -77,7 +77,7 @@
<td><span t-esc="supplier.name" class="table-name"/>:</td>
<div class="mobile-line">
<td><t t-esc="supplier.delay"/> Days</td>
<td t-if="_hasMarginsCostsAccessRights()"><t t-esc="env.pos.format_currency(supplier.price)"/></td>
<td t-if="_hasMarginsCostsAccessRights()"><t t-esc="pos.globalState.format_currency(supplier.price)"/></td>
</div>
</tr>
</t>
@@ -13,7 +13,7 @@
<tr>
<td><span class="searchable" t-esc="optional.name" t-on-click="() => this.searchProduct(optional.name)"/></td>
<td class="table-value">
from <t t-esc="env.pos.format_currency(optional.price)"/>
from <t t-esc="pos.globalState.format_currency(optional.price)"/>
</td>
</tr>
</t>