summaryrefslogtreecommitdiff
path: root/addons/point_of_sale/static/src/js/Screens/ReceiptScreen
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/point_of_sale/static/src/js/Screens/ReceiptScreen
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/point_of_sale/static/src/js/Screens/ReceiptScreen')
-rw-r--r--addons/point_of_sale/static/src/js/Screens/ReceiptScreen/OrderReceipt.js47
-rw-r--r--addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js123
-rw-r--r--addons/point_of_sale/static/src/js/Screens/ReceiptScreen/WrappedProductNameLines.js18
3 files changed, 188 insertions, 0 deletions
diff --git a/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/OrderReceipt.js b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/OrderReceipt.js
new file mode 100644
index 00000000..c06b6339
--- /dev/null
+++ b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/OrderReceipt.js
@@ -0,0 +1,47 @@
+odoo.define('point_of_sale.OrderReceipt', function(require) {
+ 'use strict';
+
+ const PosComponent = require('point_of_sale.PosComponent');
+ const Registries = require('point_of_sale.Registries');
+
+ class OrderReceipt extends PosComponent {
+ constructor() {
+ super(...arguments);
+ this._receiptEnv = this.props.order.getOrderReceiptEnv();
+ }
+ willUpdateProps(nextProps) {
+ this._receiptEnv = nextProps.order.getOrderReceiptEnv();
+ }
+ get receipt() {
+ return this.receiptEnv.receipt;
+ }
+ get orderlines() {
+ return this.receiptEnv.orderlines;
+ }
+ get paymentlines() {
+ return this.receiptEnv.paymentlines;
+ }
+ get isTaxIncluded() {
+ return Math.abs(this.receipt.subtotal - this.receipt.total_with_tax) <= 0.000001;
+ }
+ get receiptEnv () {
+ return this._receiptEnv;
+ }
+ isSimple(line) {
+ return (
+ line.discount === 0 &&
+ line.is_in_unit &&
+ line.quantity === 1 &&
+ !(
+ line.display_discount_policy == 'without_discount' &&
+ line.price < line.price_lst
+ )
+ );
+ }
+ }
+ OrderReceipt.template = 'OrderReceipt';
+
+ Registries.Component.add(OrderReceipt);
+
+ return OrderReceipt;
+});
diff --git a/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js
new file mode 100644
index 00000000..720c65e4
--- /dev/null
+++ b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/ReceiptScreen.js
@@ -0,0 +1,123 @@
+odoo.define('point_of_sale.ReceiptScreen', function (require) {
+ 'use strict';
+
+ const { Printer } = require('point_of_sale.Printer');
+ const { is_email } = require('web.utils');
+ const { useRef, useContext } = owl.hooks;
+ const { useErrorHandlers, onChangeOrder } = require('point_of_sale.custom_hooks');
+ const Registries = require('point_of_sale.Registries');
+ const AbstractReceiptScreen = require('point_of_sale.AbstractReceiptScreen');
+
+ const ReceiptScreen = (AbstractReceiptScreen) => {
+ class ReceiptScreen extends AbstractReceiptScreen {
+ constructor() {
+ super(...arguments);
+ useErrorHandlers();
+ onChangeOrder(null, (newOrder) => newOrder && this.render());
+ this.orderReceipt = useRef('order-receipt');
+ const order = this.currentOrder;
+ const client = order.get_client();
+ this.orderUiState = useContext(order.uiState.ReceiptScreen);
+ this.orderUiState.inputEmail = this.orderUiState.inputEmail || (client && client.email) || '';
+ this.is_email = is_email;
+ }
+ mounted() {
+ // Here, we send a task to the event loop that handles
+ // the printing of the receipt when the component is mounted.
+ // We are doing this because we want the receipt screen to be
+ // displayed regardless of what happen to the handleAutoPrint
+ // call.
+ setTimeout(async () => await this.handleAutoPrint(), 0);
+ }
+ async onSendEmail() {
+ if (!is_email(this.orderUiState.inputEmail)) {
+ this.orderUiState.emailSuccessful = false;
+ this.orderUiState.emailNotice = this.env._t('Invalid email.');
+ return;
+ }
+ try {
+ await this._sendReceiptToCustomer();
+ this.orderUiState.emailSuccessful = true;
+ this.orderUiState.emailNotice = this.env._t('Email sent.');
+ } catch (error) {
+ this.orderUiState.emailSuccessful = false;
+ this.orderUiState.emailNotice = this.env._t('Sending email failed. Please try again.');
+ }
+ }
+ get orderAmountPlusTip() {
+ const order = this.currentOrder;
+ const orderTotalAmount = order.get_total_with_tax();
+ const tip_product_id = this.env.pos.config.tip_product_id && this.env.pos.config.tip_product_id[0];
+ const tipLine = order
+ .get_orderlines()
+ .find((line) => tip_product_id && line.product.id === tip_product_id);
+ const tipAmount = tipLine ? tipLine.get_all_prices().priceWithTax : 0;
+ const orderAmountStr = this.env.pos.format_currency(orderTotalAmount - tipAmount);
+ if (!tipAmount) return orderAmountStr;
+ const tipAmountStr = this.env.pos.format_currency(tipAmount);
+ return `${orderAmountStr} + ${tipAmountStr} tip`;
+ }
+ get currentOrder() {
+ return this.env.pos.get_order();
+ }
+ get nextScreen() {
+ return { name: 'ProductScreen' };
+ }
+ whenClosing() {
+ this.orderDone();
+ }
+ /**
+ * This function is called outside the rendering call stack. This way,
+ * we don't block the displaying of ReceiptScreen when it is mounted; additionally,
+ * any error that can happen during the printing does not affect the rendering.
+ */
+ async handleAutoPrint() {
+ if (this._shouldAutoPrint()) {
+ await this.printReceipt();
+ if (this.currentOrder._printed && this._shouldCloseImmediately()) {
+ this.whenClosing();
+ }
+ }
+ }
+ orderDone() {
+ this.currentOrder.finalize();
+ const { name, props } = this.nextScreen;
+ this.showScreen(name, props);
+ }
+ async printReceipt() {
+ const isPrinted = await this._printReceipt();
+ if (isPrinted) {
+ this.currentOrder._printed = true;
+ }
+ }
+ _shouldAutoPrint() {
+ return this.env.pos.config.iface_print_auto && !this.currentOrder._printed;
+ }
+ _shouldCloseImmediately() {
+ var invoiced_finalized = this.currentOrder.is_to_invoice() ? this.currentOrder.finalized : true;
+ return this.env.pos.proxy.printer && this.env.pos.config.iface_print_skip_screen && invoiced_finalized;
+ }
+ async _sendReceiptToCustomer() {
+ const printer = new Printer();
+ const receiptString = this.orderReceipt.comp.el.outerHTML;
+ const ticketImage = await printer.htmlToImg(receiptString);
+ const order = this.currentOrder;
+ const client = order.get_client();
+ const orderName = order.get_name();
+ const orderClient = { email: this.orderUiState.inputEmail, name: client ? client.name : this.orderUiState.inputEmail };
+ const order_server_id = this.env.pos.validated_orders_name_server_id_map[orderName];
+ await this.rpc({
+ model: 'pos.order',
+ method: 'action_receipt_to_customer',
+ args: [[order_server_id], orderName, orderClient, ticketImage],
+ });
+ }
+ }
+ ReceiptScreen.template = 'ReceiptScreen';
+ return ReceiptScreen;
+ };
+
+ Registries.Component.addByExtending(ReceiptScreen, AbstractReceiptScreen);
+
+ return ReceiptScreen;
+});
diff --git a/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/WrappedProductNameLines.js b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/WrappedProductNameLines.js
new file mode 100644
index 00000000..e7527eee
--- /dev/null
+++ b/addons/point_of_sale/static/src/js/Screens/ReceiptScreen/WrappedProductNameLines.js
@@ -0,0 +1,18 @@
+odoo.define('point_of_sale.WrappedProductNameLines', function(require) {
+ 'use strict';
+
+ const PosComponent = require('point_of_sale.PosComponent');
+ const Registries = require('point_of_sale.Registries');
+
+ class WrappedProductNameLines extends PosComponent {
+ constructor() {
+ super(...arguments);
+ this.line = this.props.line;
+ }
+ }
+ WrappedProductNameLines.template = 'WrappedProductNameLines';
+
+ Registries.Component.add(WrappedProductNameLines);
+
+ return WrappedProductNameLines;
+});