diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 5f9a2cf26baf0..d7916aaa826d9 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -1212,6 +1212,11 @@ def remove_move_reconcile(self):
account_move_line.payment_id.write({'invoice_ids': [(3, invoice.id, None)]})
rec_move_ids += account_move_line.matched_debit_ids
rec_move_ids += account_move_line.matched_credit_ids
+ if self.env.context.get('invoice_id'):
+ current_invoice = self.env['account.invoice'].browse(self.env.context['invoice_id'])
+ rec_move_ids = rec_move_ids.filtered(
+ lambda r: (r.debit_move_id + r.credit_move_id) & current_invoice.move_id.line_ids
+ )
return rec_move_ids.unlink()
####################################################
diff --git a/addons/account/static/src/js/reconciliation/reconciliation_model.js b/addons/account/static/src/js/reconciliation/reconciliation_model.js
index 9894dc6a9b46a..7b80e0bbaa741 100644
--- a/addons/account/static/src/js/reconciliation/reconciliation_model.js
+++ b/addons/account/static/src/js/reconciliation/reconciliation_model.js
@@ -633,7 +633,7 @@ var StatementModel = BasicModel.extend({
handles = [handle];
} else {
_.each(this.lines, function (line, handle) {
- if (!line.reconciled && !line.balance.amount && line.reconciliation_proposition.length) {
+ if (!line.reconciled && line.balance && !line.balance.amount && line.reconciliation_proposition.length) {
handles.push(handle);
}
});
diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py
index 4840e40f41a1d..09945c6e15baf 100644
--- a/addons/account/tests/test_reconciliation.py
+++ b/addons/account/tests/test_reconciliation.py
@@ -625,6 +625,42 @@ def test_partial_reconcile_currencies_01(self):
full_rec_payable = full_rec_move.line_ids.filtered(lambda l: l.account_id == self.account_rsa)
self.assertEqual(full_rec_payable.balance, 18.75)
+ def test_unreconcile(self):
+ # Use case:
+ # 2 invoices paid with a single payment. Unreconcile the payment with one invoice, the
+ # other invoice should remain reconciled.
+ inv1 = self.create_invoice(invoice_amount=10, currency_id=self.currency_usd_id)
+ inv2 = self.create_invoice(invoice_amount=20, currency_id=self.currency_usd_id)
+ payment = self.env['account.payment'].create({
+ 'payment_type': 'inbound',
+ 'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id,
+ 'partner_type': 'customer',
+ 'partner_id': self.partner_agrolait_id,
+ 'amount': 100,
+ 'currency_id': self.currency_usd_id,
+ 'journal_id': self.bank_journal_usd.id,
+ })
+ payment.post()
+ credit_aml = payment.move_line_ids.filtered('credit')
+
+ # Check residual before assignation
+ self.assertAlmostEquals(inv1.residual, 10)
+ self.assertAlmostEquals(inv2.residual, 20)
+
+ # Assign credit and residual
+ inv1.assign_outstanding_credit(credit_aml.id)
+ inv2.assign_outstanding_credit(credit_aml.id)
+ self.assertAlmostEquals(inv1.residual, 0)
+ self.assertAlmostEquals(inv2.residual, 0)
+
+ # Unreconcile one invoice at a time and check residual
+ credit_aml.with_context(invoice_id=inv1.id).remove_move_reconcile()
+ self.assertAlmostEquals(inv1.residual, 10)
+ self.assertAlmostEquals(inv2.residual, 0)
+ credit_aml.with_context(invoice_id=inv2.id).remove_move_reconcile()
+ self.assertAlmostEquals(inv1.residual, 10)
+ self.assertAlmostEquals(inv2.residual, 20)
+
def test_partial_reconcile_currencies_02(self):
####
# Day 1: Invoice Cust/001 to customer (expressed in USD)
diff --git a/addons/account_payment/models/payment.py b/addons/account_payment/models/payment.py
index 0ad11d39788a8..389cfa206e1d2 100644
--- a/addons/account_payment/models/payment.py
+++ b/addons/account_payment/models/payment.py
@@ -175,3 +175,10 @@ def _check_or_create_invoice_tx(self, invoice, acquirer, payment_token=None, tx_
})
return tx
+
+ def _post_process_after_done(self, **kwargs):
+ # set invoice id in payment transaction when payment being done from sale order
+ res = super(PaymentTransaction, self)._post_process_after_done()
+ if kwargs.get('invoice_id'):
+ self.account_invoice_id = kwargs['invoice_id']
+ return res
diff --git a/addons/barcodes/static/src/js/barcode_events.js b/addons/barcodes/static/src/js/barcode_events.js
index e02d3aafdb7cc..71e07030ffd34 100644
--- a/addons/barcodes/static/src/js/barcode_events.js
+++ b/addons/barcodes/static/src/js/barcode_events.js
@@ -28,6 +28,12 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
// Keys from a barcode scanner are usually processed as quick as possible,
// but some scanners can use an intercharacter delay (we support <= 50 ms)
max_time_between_keys_in_ms: session.max_time_between_keys_in_ms || 55,
+ // To be able to receive the barcode value, an input must be focused.
+ // On mobile devices, this causes the virtual keyboard to open.
+ // Unfortunately it is not possible to avoid this behavior...
+ // To avoid keyboard flickering at each detection of a barcode value,
+ // we want to keep it open for a while (800 ms).
+ inputTimeOut: 800,
init: function() {
mixins.PropertiesMixin.init.call(this);
@@ -38,6 +44,30 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
// Bind event handler once the DOM is loaded
// TODO: find a way to be active only when there are listeners on the bus
$(_.bind(this.start, this, false));
+
+ // Mobile device detection
+ var isMobile = navigator.userAgent.match(/Android/i) ||
+ navigator.userAgent.match(/webOS/i) ||
+ navigator.userAgent.match(/iPhone/i) ||
+ navigator.userAgent.match(/iPad/i) ||
+ navigator.userAgent.match(/iPod/i) ||
+ navigator.userAgent.match(/BlackBerry/i) ||
+ navigator.userAgent.match(/Windows Phone/i);
+ this.isChromeMobile = isMobile && window.chrome;
+
+ // Creates an input who will receive the barcode scanner value.
+ if (this.isChromeMobile) {
+ this.$barcodeInput = $('', {
+ name: 'barcode',
+ type: 'text',
+ css: {
+ 'position': 'absolute',
+ 'opacity': 0,
+ },
+ });
+ }
+
+ this.__removeBarcodeField = _.debounce(this._removeBarcodeField, this.inputTimeOut);
},
handle_buffered_keys: function() {
@@ -109,7 +139,7 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
e.key === "ArrowUp" || e.key === "ArrowDown" ||
e.key === "Escape" || e.key === "Tab" ||
e.key === "Backspace" || e.key === "Delete" ||
- /F\d\d?/.test(e.key)) {
+ e.key === "Unidentified" || /F\d\d?/.test(e.key)) {
return true;
} else {
return false;
@@ -167,8 +197,84 @@ var BarcodeEvents = core.Class.extend(mixins.PropertiesMixin, {
}
},
+ /**
+ * Try to detect the barcode value by listening all keydown events:
+ * Checks if a dom element who may contains text value has the focus.
+ * If not, it's probably because these events are triggered by a barcode scanner.
+ * To be able to handle this value, a focused input will be created.
+ *
+ * This function also has the responsibility to detect the end of the barcode value.
+ * (1) In most of cases, an optional key (tab or enter) is sent to mark the end of the value.
+ * So, we direclty handle the value.
+ * (2) If no end key is configured, we have to calculate the delay between each keydowns.
+ * 'max_time_between_keys_in_ms' depends of the device and may be configured.
+ * Exceeded this timeout, we consider that the barcode value is entirely sent.
+ *
+ * @private
+ * @param {jQuery.Event} e keydown event
+ */
+ _listenBarcodeScanner: function (e) {
+ if (!$('input:text:focus, textarea:focus, [contenteditable]:focus').length) {
+ $('body').append(this.$barcodeInput);
+ this.$barcodeInput.focus();
+ }
+ if (this.$barcodeInput.is(":focus")) {
+ // Handle buffered keys immediately if the keypress marks the end
+ // of a barcode or after x milliseconds without a new keypress.
+ clearTimeout(this.timeout);
+ // On chrome mobile, e.which only works for some special characters like ENTER or TAB.
+ if (String.fromCharCode(e.which).match(this.suffix)) {
+ this._handleBarcodeValue(e);
+ } else {
+ this.timeout = setTimeout(this._handleBarcodeValue.bind(this, e),
+ this.max_time_between_keys_in_ms);
+ }
+ // if the barcode input doesn't receive keydown for a while, remove it.
+ this.__removeBarcodeField();
+ }
+ },
+
+ /**
+ * Retrieves the barcode value from the temporary input element.
+ * This checks this value and trigger it on the bus.
+ *
+ * @private
+ * @param {jQuery.Event} keydown event
+ */
+ _handleBarcodeValue: function (e) {
+ var barcodeValue = this.$barcodeInput.val();
+ if (barcodeValue.match(this.regexp)) {
+ core.bus.trigger('barcode_scanned', barcodeValue, $(e.target).parent()[0]);
+ this.$barcodeInput.val('');
+ }
+ },
+
+ /**
+ * Remove the temporary input created to store the barcode value.
+ * If nothing happens, this input will be removed, so the focus will be lost
+ * and the virtual keyboard on mobile devices will be closed.
+ *
+ * @private
+ */
+ _removeBarcodeField: function () {
+ if (this.$barcodeInput) {
+ // Reset the value and remove from the DOM.
+ this.$barcodeInput.val('').remove();
+ }
+ },
+
start: function(prevent_key_repeat){
- $('body').bind("keypress", this.__handler);
+ // Chrome Mobile isn't triggering keypress event.
+ // This is marked as Legacy in the DOM-Level-3 Standard.
+ // See: https://www.w3.org/TR/uievents/#legacy-keyboardevent-event-types
+ // This fix is only applied for Google Chrome Mobile but it should work for
+ // all other cases.
+ // In master, we could remove the behavior with keypress and only use keydown.
+ if (this.isChromeMobile) {
+ $('body').on("keydown", this._listenBarcodeScanner.bind(this));
+ } else {
+ $('body').bind("keypress", this.__handler);
+ }
if (prevent_key_repeat === true) {
$('body').bind("keydown", this.__keydown_handler);
$('body').bind('keyup', this.__keyup_handler);
diff --git a/addons/base_import/models/base_import.py b/addons/base_import/models/base_import.py
index f5af6b8948350..ff59aff918a38 100644
--- a/addons/base_import/models/base_import.py
+++ b/addons/base_import/models/base_import.py
@@ -622,9 +622,11 @@ def _parse_import_data_recursive(self, model, prefix, data, import_fields, optio
# versions, for both data and pattern
user_format = pycompat.to_native(options.get('%s_format' % field['type']))
for num, line in enumerate(data):
+ if line[index]:
+ line[index] = line[index].strip()
if line[index]:
try:
- line[index] = dt.strftime(dt.strptime(pycompat.to_native(line[index].strip()), user_format), server_format)
+ line[index] = dt.strftime(dt.strptime(pycompat.to_native(line[index]), user_format), server_format)
except ValueError as e:
raise ValueError(_("Column %s contains incorrect values. Error in line %d: %s") % (name, num + 1, e))
except Exception as e:
diff --git a/addons/hr/models/mail_alias.py b/addons/hr/models/mail_alias.py
index f98fce32f5ae9..c224d21df074b 100644
--- a/addons/hr/models/mail_alias.py
+++ b/addons/hr/models/mail_alias.py
@@ -14,7 +14,7 @@ class MailAlias(models.AbstractModel):
_inherit = 'mail.alias.mixin'
def _alias_check_contact_on_record(self, record, message, message_dict, alias):
- if alias.alias_contact == 'employees' and record.ids:
+ if alias.alias_contact == 'employees':
email_from = tools.decode_message_header(message, 'From')
email_address = tools.email_split(email_from)[0]
employee = self.env['hr.employee'].search([('work_email', 'ilike', email_address)], limit=1)
diff --git a/addons/l10n_ch/i18n_extra/de_CH.po b/addons/l10n_ch/i18n_extra/de_CH.po
index 23e7511b4729b..0f9c0b787265e 100644
--- a/addons/l10n_ch/i18n_extra/de_CH.po
+++ b/addons/l10n_ch/i18n_extra/de_CH.po
@@ -604,7 +604,7 @@ msgstr "Bankverbindlichkeiten"
#: model:account.account,name:l10n_ch.1_ch_coa_2160
#: model:account.account.template,name:l10n_ch.ch_coa_2160
msgid "Dettes envers l'actionnaire"
-msgstr ""
+msgstr "Gesellschafterverbindlichkeiten"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3806
@@ -612,7 +612,7 @@ msgstr ""
#: model:account.account.template,name:l10n_ch.ch_coa_3806
#: model:account.account.template,name:l10n_ch.ch_coa_4906
msgid "Différences de change"
-msgstr ""
+msgstr "Währungsdifferenzen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_2261
@@ -624,7 +624,7 @@ msgstr "Beschlossene Ausschüttungen"
#: model:account.account,name:l10n_ch.1_ch_coa_4071
#: model:account.account.template,name:l10n_ch.ch_coa_4071
msgid "Droits de douanes à l'importation"
-msgstr ""
+msgstr "Einfuhrzölle"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1109
@@ -648,7 +648,7 @@ msgstr "Abrechnungskonto MWST"
#: model:account.account,name:l10n_ch.1_ch_coa_4009
#: model:account.account.template,name:l10n_ch.ch_coa_4009
msgid "Déductions obtenues sur achats"
-msgstr ""
+msgstr "Einkaufsrabatte"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3009
@@ -714,7 +714,7 @@ msgstr "Unterhalt, Reparaturen, Ersatz mobile Sachanlagen"
#: model:account.account,name:l10n_ch.1_ch_coa_1570
#: model:account.account.template,name:l10n_ch.ch_coa_1570
msgid "Equipements et Installations"
-msgstr ""
+msgstr "Feste Einrichtungen und Installationen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3800
@@ -722,7 +722,7 @@ msgstr ""
#: model:account.account.template,name:l10n_ch.ch_coa_3800
#: model:account.account.template,name:l10n_ch.ch_coa_4900
msgid "Escomptes"
-msgstr ""
+msgstr "Erlösminderungen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4530
@@ -734,31 +734,31 @@ msgstr "Benzin"
#: model:account.account,name:l10n_ch.1_ch_coa_3804
#: model:account.account.template,name:l10n_ch.ch_coa_3804
msgid "Frais d'encaissement"
-msgstr "Frais d'encaissement"
+msgstr "Inkassoaufwand"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3807
#: model:account.account.template,name:l10n_ch.ch_coa_3807
msgid "Frais d'expédition"
-msgstr "Frais d'expédition"
+msgstr "Versandkosten"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4072
#: model:account.account.template,name:l10n_ch.ch_coa_4072
msgid "Frais de transport à l'achat"
-msgstr "Frais de transport à l'achat"
+msgstr "Transportkosten"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4070
#: model:account.account.template,name:l10n_ch.ch_coa_4070
msgid "Frêts à l'achat"
-msgstr ""
+msgstr "Frachtkosten"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4510
#: model:account.account.template,name:l10n_ch.ch_coa_4510
msgid "Gaz"
-msgstr "Gaz"
+msgstr "Gas"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1770
@@ -992,7 +992,7 @@ msgstr "Beteiligungen"
#: model:account.account,name:l10n_ch.1_ch_coa_4086
#: model:account.account.template,name:l10n_ch.ch_coa_4086
msgid "Pertes de matières"
-msgstr ""
+msgstr "Warenschwund"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3805
@@ -1125,13 +1125,13 @@ msgstr "Werbeaufwand"
#: model:account.account,name:l10n_ch.1_ch_coa_3801
#: model:account.account.template,name:l10n_ch.ch_coa_3801
msgid "Rabais et réduction de prix"
-msgstr ""
+msgstr "Rabatte und Preisreduktionen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4901
#: model:account.account.template,name:l10n_ch.ch_coa_4901
msgid "Rabais et réductions de prix"
-msgstr ""
+msgstr "Rabatte und Preisreduktionen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3802
@@ -1139,7 +1139,7 @@ msgstr ""
#: model:account.account.template,name:l10n_ch.ch_coa_3802
#: model:account.account.template,name:l10n_ch.ch_coa_4092
msgid "Ristournes"
-msgstr ""
+msgstr "Rückvergütungen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_2940
@@ -1473,13 +1473,13 @@ msgstr "Wertschriften"
#: model:account.account,name:l10n_ch.1_transfer_account_id
#: model:account.account.template,name:l10n_ch.transfer_account_id
msgid "Transferts internes"
-msgstr ""
+msgstr "Interne Verrechnungen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1280
#: model:account.account.template,name:l10n_ch.ch_coa_1280
msgid "Travaux en cours"
-msgstr "Unfertige Erzeugnisse"
+msgstr "Nicht fakturierte Dienstleistungen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3940
@@ -1491,19 +1491,19 @@ msgstr "Bestandesänderungen nicht fakturierte Dienstleistungen"
#: model:account.account,name:l10n_ch.1_ch_coa_1287
#: model:account.account.template,name:l10n_ch.ch_coa_1287
msgid "Variation de la valeur des travaux en cours"
-msgstr ""
+msgstr "Bestandesänderungen nicht fakturierte Dienstleistungen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1277
#: model:account.account.template,name:l10n_ch.ch_coa_1277
msgid "Variation de stock produits semi-ouvrés"
-msgstr ""
+msgstr "Bestandesänderungen unfertige Erzeugnisse"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1267
#: model:account.account.template,name:l10n_ch.ch_coa_1267
msgid "Variation de stocks de produits finis"
-msgstr ""
+msgstr "Bestandesänderungen fertige Erzeugnisse"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_1207
@@ -1511,13 +1511,13 @@ msgstr ""
#: model:account.account.template,name:l10n_ch.ch_coa_1207
#: model:account.account.template,name:l10n_ch.ch_coa_4800
msgid "Variation des stocks de marchandises"
-msgstr ""
+msgstr "Bestandesänderungen Handelsware"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4801
#: model:account.account.template,name:l10n_ch.ch_coa_4801
msgid "Variation des stocks de matières premières"
-msgstr ""
+msgstr "Bestandesänderungen Rohstoffe"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3901
@@ -1535,7 +1535,7 @@ msgstr "Bestandesänderungen unfertige Erzeugnisse"
#: model:account.account,name:l10n_ch.1_ch_coa_1217
#: model:account.account.template,name:l10n_ch.ch_coa_1217
msgid "Variation des stocks des matières premières"
-msgstr ""
+msgstr "Bestandesänderungen Rohstoffe"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_4008
@@ -1543,7 +1543,7 @@ msgstr ""
#: model:account.account.template,name:l10n_ch.ch_coa_4008
#: model:account.account.template,name:l10n_ch.ch_coa_4080
msgid "Variations de stocks"
-msgstr ""
+msgstr "Inventurdifferenzen"
#. module: l10n_ch
#: model:account.account,name:l10n_ch.1_ch_coa_3200
diff --git a/addons/l10n_ch/static/src/less/report_isr.less b/addons/l10n_ch/static/src/less/report_isr.less
index 913404727d25c..83de6851409a7 100644
--- a/addons/l10n_ch/static/src/less/report_isr.less
+++ b/addons/l10n_ch/static/src/less/report_isr.less
@@ -19,12 +19,18 @@ body.l10n_ch_isr {
}
}
}
-}
-/* content outside isr needs margins to not overlap header */
-body.l10n_ch_isr #content_outside_isr {
- padding: 15px;
- padding-top: 150px;
+ /* content outside isr needs margins to not overlap header */
+ #content_outside_isr {
+ padding: 15px;
+ padding-top: 150px;
+ }
+
+ /* ISR is intended for pre-printed paper, we don't want stylistic background */
+ .o_report_layout_background {
+ background: none;
+ min-height: 0;
+ }
}
body.l10n_ch_isr #isr {
diff --git a/addons/mail/i18n/zh_CN.po b/addons/mail/i18n/zh_CN.po
index 94e1807945b12..416f31bcffc31 100644
--- a/addons/mail/i18n/zh_CN.po
+++ b/addons/mail/i18n/zh_CN.po
@@ -144,10 +144,6 @@ msgid ""
"object.parent_id.subject) or (object.parent_id and "
"object.parent_id.record_name and 'Re: %s' % object.parent_id.record_name)}"
msgstr ""
-"${object.subject 或 (object.record_name 和 'Re: %s' % object.record_name) 或 "
-"(object.parent_id and object.parent_id.subject 和 'Re: %s' % "
-"object.parent_id.subject) 或 (object.parent_id 和 object.parent_id.record_name"
-" 和 'Re: %s' % object.parent_id.record_name)}"
#. module: mail
#. openerp-web
diff --git a/addons/maintenance/views/maintenance_views.xml b/addons/maintenance/views/maintenance_views.xml
index c35bb46cdd396..f3dcca4acbbb3 100644
--- a/addons/maintenance/views/maintenance_views.xml
+++ b/addons/maintenance/views/maintenance_views.xml
@@ -508,22 +508,19 @@
-
-
-
-
-
+
-
+
+
+
diff --git a/addons/mass_mailing/models/mass_mailing.py b/addons/mass_mailing/models/mass_mailing.py
index 6989cf2b1a6e6..5eeef7641c2fb 100644
--- a/addons/mass_mailing/models/mass_mailing.py
+++ b/addons/mass_mailing/models/mass_mailing.py
@@ -794,6 +794,8 @@ def convert_links(self):
def _process_mass_mailing_queue(self):
mass_mailings = self.search([('state', 'in', ('in_queue', 'sending')), '|', ('schedule_date', '<', fields.Datetime.now()), ('schedule_date', '=', False)])
for mass_mailing in mass_mailings:
+ user = mass_mailing.write_uid or self.env.user
+ mass_mailing = mass_mailing.with_context(**user.sudo(user=user).context_get())
if len(mass_mailing.get_remaining_recipients()) > 0:
mass_mailing.state = 'sending'
mass_mailing.send_mail()
diff --git a/addons/payment/models/payment_acquirer.py b/addons/payment/models/payment_acquirer.py
index d9617a633a28b..a67aea945d792 100644
--- a/addons/payment/models/payment_acquirer.py
+++ b/addons/payment/models/payment_acquirer.py
@@ -686,6 +686,10 @@ def form_feedback(self, data, acquirer_name):
return True
+ @api.multi
+ def _post_process_after_done(self, **kwargs):
+ return True
+
# --------------------------------------------------
# SERVER2SERVER RELATED METHODS
# --------------------------------------------------
diff --git a/addons/portal/views/portal_templates.xml b/addons/portal/views/portal_templates.xml
index d93ca1f6d276a..64f24c9527150 100644
--- a/addons/portal/views/portal_templates.xml
+++ b/addons/portal/views/portal_templates.xml
@@ -281,7 +281,7 @@