diff options
| author | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
|---|---|---|
| committer | stephanchrst <stephanchrst@gmail.com> | 2022-05-10 21:51:50 +0700 |
| commit | 3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch) | |
| tree | a44932296ef4a9b71d5f010906253d8c53727726 /addons/point_of_sale/static/src/js/Screens/ReceiptScreen | |
| parent | 0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff) | |
initial commit 2
Diffstat (limited to 'addons/point_of_sale/static/src/js/Screens/ReceiptScreen')
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; +}); |
