Skip to content

Commit 936e7f4

Browse files
committed
Merge remote-tracking branch 'odoo/11.0' into 11.0
2 parents 8e95433 + 3a74afd commit 936e7f4

File tree

16 files changed

+196
-46
lines changed

16 files changed

+196
-46
lines changed

addons/account/static/src/js/reconciliation/reconciliation_model.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -614,7 +614,7 @@ var StatementModel = BasicModel.extend({
614614
handles = [handle];
615615
} else {
616616
_.each(this.lines, function (line, handle) {
617-
if (!line.reconciled && !line.balance.amount && line.reconciliation_proposition.length) {
617+
if (!line.reconciled && line.balance && !line.balance.amount && line.reconciliation_proposition.length) {
618618
handles.push(handle);
619619
}
620620
});

addons/account_payment/models/payment.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,3 +175,10 @@ def _check_or_create_invoice_tx(self, invoice, acquirer, payment_token=None, tx_
175175
})
176176

177177
return tx
178+
179+
def _post_process_after_done(self, **kwargs):
180+
# set invoice id in payment transaction when payment being done from sale order
181+
res = super(PaymentTransaction, self)._post_process_after_done()
182+
if kwargs.get('invoice_id'):
183+
self.account_invoice_id = kwargs['invoice_id']
184+
return res

addons/account_voucher/models/account_voucher.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ def onchange_date(self):
146146

147147
@api.onchange('partner_id', 'pay_now')
148148
def onchange_partner_id(self):
149+
pay_journal_domain = [('type', 'in', ['cash', 'bank'])]
149150
if self.pay_now != 'pay_now':
150151
if self.partner_id:
151152
self.account_id = self.partner_id.property_account_receivable_id \
@@ -155,6 +156,12 @@ def onchange_partner_id(self):
155156
domain = [('deprecated', '=', False), ('internal_type', '=', account_type)]
156157

157158
self.account_id = self.env['account.account'].search(domain, limit=1)
159+
else:
160+
if self.voucher_type == 'purchase':
161+
pay_journal_domain.append(('outbound_payment_method_ids', '!=', False))
162+
else:
163+
pay_journal_domain.append(('inbound_payment_method_ids', '!=', False))
164+
return {'domain': {'payment_journal_id': pay_journal_domain}}
158165

159166
@api.multi
160167
def proforma_voucher(self):

addons/barcodes/static/src/js/barcode_events.js

Lines changed: 108 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,12 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
2828
// Keys from a barcode scanner are usually processed as quick as possible,
2929
// but some scanners can use an intercharacter delay (we support <= 50 ms)
3030
max_time_between_keys_in_ms: session.max_time_between_keys_in_ms || 55,
31+
// To be able to receive the barcode value, an input must be focused.
32+
// On mobile devices, this causes the virtual keyboard to open.
33+
// Unfortunately it is not possible to avoid this behavior...
34+
// To avoid keyboard flickering at each detection of a barcode value,
35+
// we want to keep it open for a while (800 ms).
36+
inputTimeOut: 800,
3137

3238
init: function() {
3339
mixins.PropertiesMixin.init.call(this);
@@ -38,6 +44,30 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
3844
// Bind event handler once the DOM is loaded
3945
// TODO: find a way to be active only when there are listeners on the bus
4046
$(_.bind(this.start, this, false));
47+
48+
// Mobile device detection
49+
var isMobile = navigator.userAgent.match(/Android/i) ||
50+
navigator.userAgent.match(/webOS/i) ||
51+
navigator.userAgent.match(/iPhone/i) ||
52+
navigator.userAgent.match(/iPad/i) ||
53+
navigator.userAgent.match(/iPod/i) ||
54+
navigator.userAgent.match(/BlackBerry/i) ||
55+
navigator.userAgent.match(/Windows Phone/i);
56+
this.isChromeMobile = isMobile && window.chrome;
57+
58+
// Creates an input who will receive the barcode scanner value.
59+
if (this.isChromeMobile) {
60+
this.$barcodeInput = $('<input/>', {
61+
name: 'barcode',
62+
type: 'text',
63+
css: {
64+
'position': 'absolute',
65+
'opacity': 0,
66+
},
67+
});
68+
}
69+
70+
this.__removeBarcodeField = _.debounce(this._removeBarcodeField, this.inputTimeOut);
4171
},
4272

4373
handle_buffered_keys: function() {
@@ -109,7 +139,7 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
109139
e.key === "ArrowUp" || e.key === "ArrowDown" ||
110140
e.key === "Escape" || e.key === "Tab" ||
111141
e.key === "Backspace" || e.key === "Delete" ||
112-
/F\d\d?/.test(e.key)) {
142+
e.key === "Unidentified" || /F\d\d?/.test(e.key)) {
113143
return true;
114144
} else {
115145
return false;
@@ -167,8 +197,84 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
167197
}
168198
},
169199

200+
/**
201+
* Try to detect the barcode value by listening all keydown events:
202+
* Checks if a dom element who may contains text value has the focus.
203+
* If not, it's probably because these events are triggered by a barcode scanner.
204+
* To be able to handle this value, a focused input will be created.
205+
*
206+
* This function also has the responsibility to detect the end of the barcode value.
207+
* (1) In most of cases, an optional key (tab or enter) is sent to mark the end of the value.
208+
* So, we direclty handle the value.
209+
* (2) If no end key is configured, we have to calculate the delay between each keydowns.
210+
* 'max_time_between_keys_in_ms' depends of the device and may be configured.
211+
* Exceeded this timeout, we consider that the barcode value is entirely sent.
212+
*
213+
* @private
214+
* @param {jQuery.Event} e keydown event
215+
*/
216+
_listenBarcodeScanner: function (e) {
217+
if (!$('input:text:focus, textarea:focus, [contenteditable]:focus').length) {
218+
$('body').append(this.$barcodeInput);
219+
this.$barcodeInput.focus();
220+
}
221+
if (this.$barcodeInput.is(":focus")) {
222+
// Handle buffered keys immediately if the keypress marks the end
223+
// of a barcode or after x milliseconds without a new keypress.
224+
clearTimeout(this.timeout);
225+
// On chrome mobile, e.which only works for some special characters like ENTER or TAB.
226+
if (String.fromCharCode(e.which).match(this.suffix)) {
227+
this._handleBarcodeValue(e);
228+
} else {
229+
this.timeout = setTimeout(this._handleBarcodeValue.bind(this, e),
230+
this.max_time_between_keys_in_ms);
231+
}
232+
// if the barcode input doesn't receive keydown for a while, remove it.
233+
this.__removeBarcodeField();
234+
}
235+
},
236+
237+
/**
238+
* Retrieves the barcode value from the temporary input element.
239+
* This checks this value and trigger it on the bus.
240+
*
241+
* @private
242+
* @param {jQuery.Event} keydown event
243+
*/
244+
_handleBarcodeValue: function (e) {
245+
var barcodeValue = this.$barcodeInput.val();
246+
if (barcodeValue.match(this.regexp)) {
247+
core.bus.trigger('barcode_scanned', barcodeValue, $(e.target).parent()[0]);
248+
this.$barcodeInput.val('');
249+
}
250+
},
251+
252+
/**
253+
* Remove the temporary input created to store the barcode value.
254+
* If nothing happens, this input will be removed, so the focus will be lost
255+
* and the virtual keyboard on mobile devices will be closed.
256+
*
257+
* @private
258+
*/
259+
_removeBarcodeField: function () {
260+
if (this.$barcodeInput) {
261+
// Reset the value and remove from the DOM.
262+
this.$barcodeInput.val('').remove();
263+
}
264+
},
265+
170266
start: function(prevent_key_repeat){
171-
$('body').bind("keypress", this.__handler);
267+
// Chrome Mobile isn't triggering keypress event.
268+
// This is marked as Legacy in the DOM-Level-3 Standard.
269+
// See: https://www.w3.org/TR/uievents/#legacy-keyboardevent-event-types
270+
// This fix is only applied for Google Chrome Mobile but it should work for
271+
// all other cases.
272+
// In master, we could remove the behavior with keypress and only use keydown.
273+
if (this.isChromeMobile) {
274+
$('body').on("keydown", this._listenBarcodeScanner.bind(this));
275+
} else {
276+
$('body').bind("keypress", this.__handler);
277+
}
172278
if (prevent_key_repeat === true) {
173279
$('body').bind("keydown", this.__keydown_handler);
174280
$('body').bind('keyup', this.__keyup_handler);

addons/l10n_ch/static/src/less/report_isr.less

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,18 @@ body.l10n_ch_isr {
1919
}
2020
}
2121
}
22-
}
2322

24-
/* content outside isr needs margins to not overlap header */
25-
body.l10n_ch_isr #content_outside_isr {
26-
padding: 15px;
27-
padding-top: 150px;
23+
/* content outside isr needs margins to not overlap header */
24+
#content_outside_isr {
25+
padding: 15px;
26+
padding-top: 150px;
27+
}
28+
29+
/* ISR is intended for pre-printed paper, we don't want stylistic background */
30+
.o_report_layout_background {
31+
background: none;
32+
min-height: 0;
33+
}
2834
}
2935

3036
body.l10n_ch_isr #isr {

addons/mail/i18n/zh_CN.po

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
# Translation of Odoo Server.
22
# This file contains the translation of the following modules:
33
# * mail
4-
#
4+
#
55
# Translators:
66
# Jeffery CHEN Fan <[email protected]>, 2017
77
# Martin Trigaux, 2017
88
# Talway <[email protected]>, 2017
99
# niulin lnc. <[email protected]>, 2017
10-
# liAnGjiA <[email protected]>, 2017
1110
# xiaobin wu <[email protected]>, 2017
1211
# 卓忆科技 <[email protected]>, 2017
1312
# Gary Wei <[email protected]>, 2017
1413
# also <[email protected]>, 2017
1514
# Joray <[email protected]>, 2017
15+
# liAnGjiA <[email protected]>, 2017
1616
# Michael Chong <[email protected]>, 2017
1717
# liulixia <[email protected]>, 2017
1818
# 厦门-许舟 <[email protected]>, 2017
@@ -43,10 +43,10 @@ msgstr ""
4343
"PO-Revision-Date: 2017-11-30 13:11+0000\n"
4444
"Last-Translator: e2f <[email protected]>, 2018\n"
4545
"Language-Team: Chinese (China) (https://www.transifex.com/odoo/teams/41243/zh_CN/)\n"
46-
"Language: zh_CN\n"
4746
"MIME-Version: 1.0\n"
4847
"Content-Type: text/plain; charset=UTF-8\n"
4948
"Content-Transfer-Encoding: \n"
49+
"Language: zh_CN\n"
5050
"Plural-Forms: nplurals=1; plural=0;\n"
5151

5252
#. module: mail
@@ -245,10 +245,6 @@ msgid ""
245245
"object.parent_id.subject) or (object.parent_id and "
246246
"object.parent_id.record_name and 'Re: %s' % object.parent_id.record_name)}"
247247
msgstr ""
248-
"${object.subject 或 (object.record_name 和 'Re: %s' % object.record_name) 或 "
249-
"(object.parent_id and object.parent_id.subject 和 'Re: %s' % "
250-
"object.parent_id.subject) 或 (object.parent_id 和 object.parent_id.record_name"
251-
" 和 'Re: %s' % object.parent_id.record_name)}"
252248

253249
#. module: mail
254250
#. openerp-web

addons/payment/models/payment_acquirer.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -684,6 +684,10 @@ def form_feedback(self, data, acquirer_name):
684684

685685
return True
686686

687+
@api.multi
688+
def _post_process_after_done(self, **kwargs):
689+
return True
690+
687691
# --------------------------------------------------
688692
# SERVER2SERVER RELATED METHODS
689693
# --------------------------------------------------

addons/sale/models/sale.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -580,20 +580,16 @@ def _get_tax_amount_by_group(self):
580580
self.ensure_one()
581581
res = {}
582582
for line in self.order_line:
583-
base_tax = 0
583+
price_reduce = line.price_unit * (1.0 - line.discount / 100.0)
584+
taxes = line.tax_id.compute_all(price_reduce, quantity=line.product_uom_qty, product=line.product_id, partner=self.partner_shipping_id)['taxes']
584585
for tax in line.tax_id:
585586
group = tax.tax_group_id
586587
res.setdefault(group, {'amount': 0.0, 'base': 0.0})
587588
# FORWARD-PORT UP TO SAAS-17
588-
price_reduce = line.price_unit * (1.0 - line.discount / 100.0)
589-
taxes = tax.compute_all(price_reduce + base_tax, quantity=line.product_uom_qty,
590-
product=line.product_id, partner=self.partner_shipping_id)['taxes']
591589
for t in taxes:
592-
res[group]['amount'] += t['amount']
593-
res[group]['base'] += t['base']
594-
if tax.include_base_amount:
595-
base_tax += tax.compute_all(price_reduce + base_tax, quantity=1, product=line.product_id,
596-
partner=self.partner_shipping_id)['taxes'][0]['amount']
590+
if t['id'] == tax.id:
591+
res[group]['amount'] += t['amount']
592+
res[group]['base'] += t['base']
597593
res = sorted(res.items(), key=lambda l: l[0].sequence)
598594
res = [(l[0].name, l[1]['amount'], l[1]['base'], len(res)) for l in res]
599595
return res

addons/sale/views/res_config_settings_views.xml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,6 @@
169169
<field name="portal_confirmation_options" class="o_light_label" widget="radio"
170170
attrs="{'required': [('portal_confirmation', '=', True)]}"/>
171171
</div>
172-
<div attrs="{'invisible': [('portal_confirmation_options', '!=', 'pay')]}">
173-
<button name='%(payment.action_payment_acquirer)d' icon="fa-arrow-right" type="action" string="Payment Acquirers" class="btn-link"/>
174-
</div>
175172
</div>
176173
</div>
177174
</div>

addons/sale_payment/__manifest__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
'views/crm_team_views.xml',
2121
'views/sale_order_views.xml',
2222
'views/sale_portal_templates.xml',
23+
'views/settings.xml',
2324
],
2425
'installable': True,
2526
'auto_install': False,

0 commit comments

Comments
 (0)