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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
|
odoo.define('point_of_sale.custom_hooks', function (require) {
'use strict';
const { Component } = owl;
const { onMounted, onPatched, onWillUnmount } = owl.hooks;
/**
* Introduce error handlers in the component.
*
* IMPROVEMENT: This is a terrible hook. There could be a better way to handle
* the error when the order failed to sync.
*/
function useErrorHandlers() {
const component = Component.current;
component._handlePushOrderError = async function (error) {
// This error handler receives `error` equivalent to `error.message` of the rpc error.
if (error.message === 'Backend Invoice') {
await this.showPopup('ConfirmPopup', {
title: this.env._t('Please print the invoice from the backend'),
body:
this.env._t(
'The order has been synchronized earlier. Please make the invoice from the backend for the order: '
) + error.data.order.name,
});
} else if (error.code < 0) {
// XmlHttpRequest Errors
const title = this.env._t('Unable to sync order');
const body = this.env._t(
'Check the internet connection then try to sync again by clicking on the red wifi button (upper right of the screen).'
);
await this.showPopup('OfflineErrorPopup', { title, body });
} else if (error.code === 200) {
// OpenERP Server Errors
await this.showPopup('ErrorTracebackPopup', {
title: error.data.message || this.env._t('Server Error'),
body:
error.data.debug ||
this.env._t('The server encountered an error while receiving your order.'),
});
} else if (error.code === 700) {
// Fiscal module errors
await this.showPopup('ErrorPopup', {
title: this.env._t('Fiscal data module error'),
body:
error.data.error.status ||
this.env._t('The fiscal data module encountered an error while receiving your order.'),
});
} else {
// ???
await this.showPopup('ErrorPopup', {
title: this.env._t('Unknown Error'),
body: this.env._t(
'The order could not be sent to the server due to an unknown error'
),
});
}
};
}
function useAutoFocusToLast() {
const current = Component.current;
let target = null;
function autofocus() {
const prevTarget = target;
const allInputs = current.el.querySelectorAll('input');
target = allInputs[allInputs.length - 1];
if (target && target !== prevTarget) {
target.focus();
target.selectionStart = target.selectionEnd = target.value.length;
}
}
onMounted(autofocus);
onPatched(autofocus);
}
/**
* Use this hook when you want to do something on previously selected and
* newly selected order when the order changes.
*
* Normally, a component is rendered then the current order is changed. When
* this happens, we want to rerender the component because the new information
* should be reflected in the screen. Additionally, we might want to remove listeners
* to the previous order and attach listeners to the new one. This hook is
* perfect for the described situation.
*
* Internally, this hook performs the following:
* 1. call newOrderCB on mounted
* 2. listen to order changes and perform the following sequence:
* - call prevOrderCB(prevOrder)
* - call newOrderCB(newOrder)
* 3. call prevOrderCB on willUnmount
*
* @param {Function} prevOrderCB apply this callback on the previous order
* @param {Function} newOrderCB apply this callback on the new order
*/
function onChangeOrder(prevOrderCB, newOrderCB) {
const current = Component.current;
prevOrderCB = prevOrderCB ? prevOrderCB.bind(current) : () => {};
newOrderCB = newOrderCB ? newOrderCB.bind(current) : () => {};
onMounted(() => {
current.env.pos.on(
'change:selectedOrder',
async (pos, newOrder) => {
await prevOrderCB(pos.previous('selectedOrder'));
await newOrderCB(newOrder);
},
current
);
newOrderCB(current.env.pos.get_order());
});
onWillUnmount(() => {
current.env.pos.off('change:selectedOrder', null, current);
prevOrderCB(current.env.pos.get_order());
});
}
function useBarcodeReader(callbackMap, exclusive = false) {
const current = Component.current;
const barcodeReader = current.env.pos.barcode_reader;
for (let [key, callback] of Object.entries(callbackMap)) {
callbackMap[key] = callback.bind(current);
}
onMounted(() => {
if (barcodeReader) {
for (let key in callbackMap) {
if (exclusive) {
barcodeReader.set_exclusive_callback(key, callbackMap[key]);
} else {
barcodeReader.set_action_callback(key, callbackMap[key]);
}
}
}
});
onWillUnmount(() => {
if (barcodeReader) {
for (let key in callbackMap) {
if (exclusive) {
barcodeReader.remove_exclusive_callback(key, callbackMap[key]);
} else {
barcodeReader.remove_action_callback(key, callbackMap[key]);
}
}
}
});
}
return { useErrorHandlers, useAutoFocusToLast, onChangeOrder, useBarcodeReader };
});
|