[IMP] website_payment: take amount change into account

Before this commit amount updates were not taken into account during the
payment operation.

After this commit amount updates are taken into account for the actual
payment operation and payment fees are updated according to the amount
and the partner country.

Part of #63133

task-2398403

Signed-off-by: Jérémy Kersten (jke) <jke@openerp.com>
This commit is contained in:
Benoit Socias
2021-09-03 02:03:15 +00:00
committed by Jeremy Kersten
parent 7fccbac004
commit e67a123227
3 changed files with 84 additions and 5 deletions
@@ -33,6 +33,19 @@ class PaymentPortal(payment_portal.PaymentPortal):
return self.payment_pay(**kwargs)
@http.route('/donation/get_acquirer_fees', type='json', auth='public', website=True, sitemap=False)
def get_acquirer_fees(self, acquirer_ids=None, amount=None, currency_id=None, country_id=None):
acquirers_sudo = request.env['payment.acquirer'].sudo().browse(acquirer_ids)
currency = request.env['res.currency'].browse(currency_id)
country = request.env['res.country'].browse(country_id)
# Compute the fees taken by acquirers supporting the feature
fees_by_acquirer = {
acq_sudo.id: acq_sudo._compute_fees(amount, currency, country)
for acq_sudo in acquirers_sudo.filtered('fees_active')
}
return fees_by_acquirer
@http.route('/donation/transaction/<minimum_amount>', type='json', auth='public', website=True, sitemap=False)
def donation_transaction(self, amount, currency_id, partner_id, access_token, minimum_amount=0, **kwargs):
if float(amount) < float(minimum_amount):
@@ -4,6 +4,10 @@ import {_t} from 'web.core';
import checkoutForm from 'payment.checkout_form';
checkoutForm.include({
events: _.extend({}, checkoutForm.prototype.events || {}, {
'change .o_wpayment_fee_impact': '_onFeeParameterChange',
}),
//--------------------------------------------------------------------------
// Private
//--------------------------------------------------------------------------
@@ -75,4 +79,62 @@ checkoutForm.include({
'donation_recipient_email': this.$('input[name="donation_recipient_email"]').val(),
} : transactionRouteParams;
},
//--------------------------------------------------------------------------
// Handlers
//--------------------------------------------------------------------------
/**
* Update the fees associated to each acquirer.
*
* Called upon change of any parameter that might impact the fees (marked with
* .o_wpayment_fee_impact).
*
* @private
* @param {Event} ev
* @return {undefined}
*/
_onFeeParameterChange: function (ev) {
const targetId = ev.target.id;
if (targetId.indexOf("amount") >= 0) {
this.txContext.amount = ev.target.value;
}
const acquirerIds = [];
for (const card of this.$('.o_payment_option_card:has(.o_payment_fee)')) {
const radio = $(card).find('input[name="o_payment_radio"]');
if (radio.data("paymentOptionType") === 'acquirer') {
acquirerIds.push(radio.data("paymentOptionId"));
}
}
const countryId = this.$('select[name="country_id"]').val();
if (acquirerIds && this.txContext.amount) {
this._rpc({
route: '/donation/get_acquirer_fees',
params: {
'acquirer_ids': acquirerIds,
'amount': this.txContext.amount !== undefined
? parseFloat(this.txContext.amount) : null,
'currency_id': this.txContext.currencyId
? parseInt(this.txContext.currencyId) : null,
'country_id': countryId,
},
}).then(feesPerAcquirer => {
for (const card of this.$('.o_payment_option_card:has(.o_payment_fee)')) {
const radio = $(card).find('input[name="o_payment_radio"]');
if (radio.data("paymentOptionType") === 'acquirer') {
const acquirerId = radio.data("paymentOptionId");
const chunk = $(card).find('.o_payment_fee .oe_currency_value')[0];
chunk.innerText = (feesPerAcquirer[acquirerId] || 0).toFixed(2);
}
}
}).guardedCatch(error => {
error.event.preventDefault();
this._displayError(
_t("Server Error"),
_t("We could not obtain payment fees."),
error.message.data.message
);
});
}
},
});
@@ -27,7 +27,7 @@
<label class="col-form-label font-weight-bold" for="country_id">Country
<span class="s_website_form_mark"> *</span>
</label>
<select t-att-disabled="'1' if country and country.id and partner_id else None" id="country_id" name="country_id" t-attf-class="form-control #{error.get('country_id') and 'is-invalid' or ''}">
<select t-att-disabled="'1' if country and country.id and partner_id else None" id="country_id" name="country_id" t-attf-class="o_wpayment_fee_impact form-control #{error.get('country_id') and 'is-invalid' or ''}">
<option value="">Country...</option>
<t t-foreach="countries" t-as="c">
<option t-att-value="c.id" t-att-selected="c.id == (country and country.id or -1)">
@@ -47,7 +47,7 @@
<div class="custom-control custom-radio my-2">
<t t-set="is_checked" t-value="float(amount) == float(donation_amount)"/>
<t t-set="has_checked" t-value="has_checked or is_checked"/>
<input class="custom-control-input" type="radio" name="amount"
<input class="o_wpayment_fee_impact custom-control-input" type="radio" name="amount"
t-attf-id="amount_#{donation_amount_index}" t-att-value="donation_amount"
t-att-checked="is_checked or None"/>
<label class="custom-control-label mt-0" t-attf-for="amount_#{donation_amount_index}">
@@ -59,7 +59,7 @@
</div>
</t>
<div t-attf-class="custom-control custom-radio my-2 #{not donation_layout and 'd-none' or ''}">
<input class="custom-control-input" type="radio" id="other_amount" name="amount"
<input class="o_wpayment_fee_impact custom-control-input" type="radio" id="other_amount" name="amount"
t-att-value="amount" t-att-checked="not has_checked or None"/>
<label class="custom-control-label mt-0 d-block" for="other_amount">
<t t-call="website_payment.donation_input">
@@ -86,6 +86,10 @@
<h3 class="o_page_header mt16 mb4">Payment Details</h3>
</t>
</xpath>
<!-- Make fee badges recognizable so that they can be updated upon amount changes -->
<xpath expr="//t[@t-if='fees_by_acquirer.get(acquirer)']/span" position="attributes">
<attribute name="class" add="o_payment_fee" separator=" "/>
</xpath>
<!-- Adapt Pay confirm button -->
<xpath expr="//t[@t-set='label']" position="after">
<t t-set="label" t-value="donation_confirm_button_label or label"/>
@@ -128,7 +132,7 @@
</template>
<template id="website_payment.donation_input" name="Donation input">
<input type="number" class="form-control o_amount_input" t-att-min="donation_options.get('minimumAmount')"
t-att-max="donation_options.get('maximumAmount')" t-att-value="amount" placeholder="Custom Amount"/>
<input type="number" class="o_wpayment_fee_impact form-control o_amount_input" t-att-min="donation_options.get('minimumAmount')"
t-att-max="donation_options.get('maximumAmount')" t-att-value="amount" placeholder="Custom Amount" id="other_amount_value"/>
</template>
</odoo>