1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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;
});
|