From 1ce17bde68a9136abae09da9eba4e363ffb32007 Mon Sep 17 00:00:00 2001 From: "Jacky (trj)" Date: Fri, 8 Apr 2022 13:14:52 +0000 Subject: [PATCH] [FIX] pos_adyen: leaving PaymentScreen while paying/cancelling Before this commit: whenever we left the PaymentScreen when we were paying (either by reloading the page or by backing to the ProductScreen), the real payment status was not properly saved even tho the payment has been paid or cancelled. With this commit: whenever we go to the PaymentScreen with a pending payment line with Adyen, we fetch the latest status from the back end. This way, the front end will always have the latest status of the payment. opw-2802676 closes odoo/odoo#90083 X-original-commit: 07b30c519b101a2998f5320dde5203bfc964b7e9 Signed-off-by: Quentin Lejeune (qle) Signed-off-by: Trinh Jacky (trj) --- .../pos_adyen/static/src/js/PaymentScreen.js | 36 +++++++++++++ addons/pos_adyen/static/src/js/models.js | 29 +++++++++-- .../pos_adyen/static/src/js/payment_adyen.js | 52 +++++++++++-------- 3 files changed, 93 insertions(+), 24 deletions(-) create mode 100644 addons/pos_adyen/static/src/js/PaymentScreen.js diff --git a/addons/pos_adyen/static/src/js/PaymentScreen.js b/addons/pos_adyen/static/src/js/PaymentScreen.js new file mode 100644 index 00000000000..8666cea23d3 --- /dev/null +++ b/addons/pos_adyen/static/src/js/PaymentScreen.js @@ -0,0 +1,36 @@ +odoo.define('pos_adyen.PaymentScreen', function(require) { + "use strict"; + + const PaymentScreen = require('point_of_sale.PaymentScreen'); + const Registries = require('point_of_sale.Registries'); + const { onMounted } = owl; + + const PosAdyenPaymentScreen = PaymentScreen => class extends PaymentScreen { + setup() { + super.setup(); + onMounted(() => { + const pendingPaymentLine = this.currentOrder.paymentlines.find( + paymentLine => paymentLine.payment_method.use_payment_terminal === 'adyen' && + (!paymentLine.is_done() && paymentLine.get_payment_status() !== 'pending') + ); + if (pendingPaymentLine) { + const paymentTerminal = pendingPaymentLine.payment_method.payment_terminal; + paymentTerminal.set_most_recent_service_id(pendingPaymentLine.terminalServiceId); + pendingPaymentLine.set_payment_status('waiting'); + paymentTerminal.start_get_status_polling().then(isPaymentSuccessful => { + if (isPaymentSuccessful) { + pendingPaymentLine.set_payment_status('done'); + pendingPaymentLine.can_be_reversed = paymentTerminal.supports_reversals; + } else { + pendingPaymentLine.set_payment_status('retry'); + } + }); + } + }); + } + }; + + Registries.Component.extend(PaymentScreen, PosAdyenPaymentScreen); + + return PaymentScreen; +}); diff --git a/addons/pos_adyen/static/src/js/models.js b/addons/pos_adyen/static/src/js/models.js index 12960e65863..802fd2b0bae 100644 --- a/addons/pos_adyen/static/src/js/models.js +++ b/addons/pos_adyen/static/src/js/models.js @@ -1,6 +1,29 @@ odoo.define('pos_adyen.models', function (require) { -var models = require('point_of_sale.models'); -var PaymentAdyen = require('pos_adyen.payment'); +const { register_payment_method, Payment } = require('point_of_sale.models'); +const PaymentAdyen = require('pos_adyen.payment'); +const Registries = require('point_of_sale.Registries'); -models.register_payment_method('adyen', PaymentAdyen); +register_payment_method('adyen', PaymentAdyen); + +const PosAdyenPayment = (Payment) => class PosAdyenPayment extends Payment { + constructor(obj, options) { + super(...arguments); + this.terminalServiceId = this.terminalServiceId || null; + } + //@override + export_as_JSON() { + const json = super.export_as_JSON(...arguments); + json.terminal_service_id = this.terminalServiceId; + return json; + } + //@override + init_from_JSON(json) { + super.init_from_JSON(...arguments); + this.terminalServiceId = json.terminal_service_id; + } + setTerminalServiceId(id) { + this.terminalServiceId = id; + } +} +Registries.Model.extend(Payment, PosAdyenPayment); }); diff --git a/addons/pos_adyen/static/src/js/payment_adyen.js b/addons/pos_adyen/static/src/js/payment_adyen.js index 2d5e62e431f..ee3ccc92046 100644 --- a/addons/pos_adyen/static/src/js/payment_adyen.js +++ b/addons/pos_adyen/static/src/js/payment_adyen.js @@ -12,7 +12,7 @@ var PaymentAdyen = PaymentInterface.extend({ send_payment_request: function (cid) { this._super.apply(this, arguments); this._reset_state(); - return this._adyen_pay(); + return this._adyen_pay(cid); }, send_payment_cancel: function (order, cid) { this._super.apply(this, arguments); @@ -24,6 +24,10 @@ var PaymentAdyen = PaymentInterface.extend({ this._super.apply(this, arguments); }, + set_most_recent_service_id(id) { + this.most_recent_service_id = id; + }, + // private methods _reset_state: function () { this.was_cancelled = false; @@ -110,7 +114,7 @@ var PaymentAdyen = PaymentInterface.extend({ return data; }, - _adyen_pay: function () { + _adyen_pay: function (cid) { var self = this; var order = this.pos.get_order(); @@ -125,7 +129,8 @@ var PaymentAdyen = PaymentInterface.extend({ } var data = this._adyen_pay_data(); - + var line = order.paymentlines.find(paymentLine => paymentLine.cid === cid); + line.setTerminalServiceId(this.most_recent_service_id); return this._call_adyen(data).then(function (data) { return self._adyen_handle_response(data); }); @@ -265,6 +270,8 @@ var PaymentAdyen = PaymentInterface.extend({ self._show_error(_t('The connection to your payment terminal failed. Please check if it is still connected to the internet.')); self._adyen_cancel(); resolve(false); + } else { + line.set_payment_status('waitingCard') } }); }, @@ -296,27 +303,30 @@ var PaymentAdyen = PaymentInterface.extend({ return Promise.resolve(); } else { line.set_payment_status('waitingCard'); - - var self = this; - var res = new Promise(function (resolve, reject) { - // clear previous intervals just in case, otherwise - // it'll run forever - clearTimeout(self.polling); - - self.polling = setInterval(function () { - self._poll_for_response(resolve, reject); - }, 5500); - }); - - // make sure to stop polling when we're done - res.finally(function () { - self._reset_state(); - }); - - return res; + return this.start_get_status_polling() } }, + start_get_status_polling() { + var self = this; + var res = new Promise(function (resolve, reject) { + // clear previous intervals just in case, otherwise + // it'll run forever + clearTimeout(self.polling); + self._poll_for_response(resolve, reject); + self.polling = setInterval(function () { + self._poll_for_response(resolve, reject); + }, 5500); + }); + + // make sure to stop polling when we're done + res.finally(function () { + self._reset_state(); + }); + + return res; + }, + _show_error: function (msg, title) { if (!title) { title = _t('Adyen Error');