[REF] payment(_*): compute feature fields

Computing the fields instead of storing them allows to implement the
feature for each provider more easily, without needing a migration
script.

task-2841744

closes odoo/odoo#91961

Related: odoo/enterprise#27618
Related: odoo/upgrade#3535
Signed-off-by: Antoine Vandevenne (anv) <anv@odoo.com>
This commit is contained in:
Demesmaeker
2022-05-24 19:10:55 +02:00
committed by Antoine Vandevenne (anv)
parent 70f844e7a1
commit 86ff8c6e8f
25 changed files with 113 additions and 63 deletions
+22 -3
View File
@@ -99,12 +99,19 @@ class PaymentAcquirer(models.Model):
default=lambda self: _("Your payment has been cancelled."), translate=True)
# Feature support fields
support_authorization = fields.Boolean(string="Authorize Mechanism Supported")
support_fees_computation = fields.Boolean(string="Fees Computation Supported")
support_tokenization = fields.Boolean(string="Tokenization Supported")
support_fees = fields.Boolean(
string="Fees Supported", compute='_compute_feature_support_fields'
)
support_manual_capture = fields.Boolean(
string="Manual Capture Supported", compute='_compute_feature_support_fields'
)
support_refund = fields.Selection(
string="Type of Refund Supported",
selection=[('full_only', "Full Only"), ('partial', "Partial")],
compute='_compute_feature_support_fields',
)
support_tokenization = fields.Boolean(
string="Tokenization Supported", compute='_compute_feature_support_fields'
)
# Kanban view fields
@@ -204,6 +211,18 @@ class PaymentAcquirer(models.Model):
elif payment_method_line:
payment_method_line.unlink()
def _compute_feature_support_fields(self):
""" Compute the feature support fields.
For an acquirer to support one or more additional feature, it must override this method.
:return: None
"""
self.update(dict.fromkeys(
('support_fees', 'support_manual_capture', 'support_refund', 'support_tokenization'),
None,
))
def _get_default_payment_method_id(self):
self.ensure_one()
return self.env.ref('account.account_payment_method_manual_in').id
+1 -1
View File
@@ -159,7 +159,7 @@ class PaymentTransaction(models.Model):
def _check_state_authorized_supported(self):
""" Check that authorization is supported for a transaction in the 'authorized' state. """
illegal_authorize_state_txs = self.filtered(
lambda tx: tx.state == 'authorized' and not tx.acquirer_id.support_authorization
lambda tx: tx.state == 'authorized' and not tx.acquirer_id.support_manual_capture
)
if illegal_authorize_state_txs:
raise ValidationError(_(
+1 -1
View File
@@ -36,7 +36,7 @@ class TestPayments(PaymentCommon):
def test_full_amount_available_for_refund_when_refunds_are_pending(self):
self.acquirer.write({
'support_refund': 'full_only', # Should simply not be False
'support_authorization': True, # To create transaction in the 'authorized' state
'support_manual_capture': True, # To create transaction in the 'authorized' state
})
tx = self.create_transaction('redirect', state='done')
tx._reconcile_after_done() # Create the payment
@@ -6,8 +6,8 @@
<field name="model">payment.acquirer</field>
<field name="arch" type="xml">
<form string="Payment Acquirer">
<field name="support_authorization" invisible="1"/>
<field name="support_fees_computation" invisible="1"/>
<field name="support_fees" invisible="1"/>
<field name="support_manual_capture" invisible="1"/>
<field name="support_tokenization" invisible="1"/>
<field name="module_id" invisible="1"/>
<field name="module_state" invisible="1"/>
@@ -57,7 +57,7 @@
<field name="display_as" placeholder="If not defined, the acquirer name will be used."/>
<field name="payment_icon_ids" attrs="{'invisible': [('show_payment_icon_ids', '=', False)]}" widget="many2many_tags"/>
<field name="allow_tokenization" attrs="{'invisible': ['|', ('support_tokenization', '=', False), ('show_allow_tokenization', '=', False)]}"/>
<field name="capture_manually" attrs="{'invisible': [('support_authorization', '=', False)]}"/>
<field name="capture_manually" attrs="{'invisible': [('support_manual_capture', '=', False)]}"/>
</group>
<group string="Availability" name="availability">
<field name="country_ids" widget="many2many_tags" placeholder="Select countries. Leave empty to use everywhere." options="{'no_open': True, 'no_create': True}"/>
@@ -68,7 +68,7 @@
</group>
</group>
</page>
<page string="Fees" name="fees" attrs="{'invisible': [('support_fees_computation', '=', False)]}">
<page string="Fees" name="fees" attrs="{'invisible': [('support_fees', '=', False)]}">
<group name="payment_fees">
<field name="fees_active"/>
<field name="fees_dom_fixed" attrs="{'invisible': [('fees_active', '=', False)]}"/>
@@ -83,7 +83,7 @@
<group>
<field name="pre_msg" attrs="{'invisible': [('show_pre_msg', '=', False)]}"/>
<field name="pending_msg" attrs="{'invisible': [('show_pending_msg', '=', False)]}"/>
<field name="auth_msg" attrs="{'invisible': ['|', ('support_authorization', '=', False), ('show_auth_msg', '=', False)]}"/>
<field name="auth_msg" attrs="{'invisible': ['|', ('support_manual_capture', '=', False), ('show_auth_msg', '=', False)]}"/>
<field name="done_msg" attrs="{'invisible': [('show_done_msg', '=', False)]}"/>
<field name="cancel_msg" attrs="{'invisible': [('show_cancel_msg', '=', False)]}"/>
</group>
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_adyen" model="payment.acquirer">
<field name="provider">adyen</field>
<field name="inline_form_view_id" ref="inline_form"/>
<field name="support_authorization">True</field>
<field name="support_fees_computation">False</field>
<field name="support_refund">partial</field>
<field name="support_tokenization">True</field>
<field name="allow_tokenization">True</field>
</record>
@@ -61,6 +61,17 @@ class PaymentAcquirer(models.Model):
if values.get(field_name): # Test the value in case we're duplicating an acquirer
values[field_name] = re.sub(r'[vV]\d+(/.*)?', '', values[field_name])
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'adyen').update({
'support_manual_capture': True,
'support_refund': 'partial',
'support_tokenization': True,
})
#=== BUSINESS METHODS ===#
def _adyen_make_request(
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_alipay" model="payment.acquirer">
<field name="provider">alipay</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">True</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_alipay" model="account.payment.method">
@@ -29,6 +29,17 @@ class PaymentAcquirer(models.Model):
alipay_seller_email = fields.Char(
string="Alipay Seller Email", help="The public Alipay partner email")
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'alipay').update({
'support_fees': True,
})
# === BUSINESS METHODS ===#
@api.model
def _get_compatible_acquirers(self, *args, currency_id=None, **kwargs):
""" Override of payment to unlist Alipay acquirers for unsupported currencies. """
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_authorize" model="payment.acquirer">
<field name="provider">authorize</field>
<field name="inline_form_view_id" ref="inline_form"/>
<field name="support_authorization">True</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">True</field>
<field name="allow_tokenization">True</field>
</record>
@@ -39,6 +39,8 @@ class PaymentAcquirer(models.Model):
required_if_provider='authorize',
)
# === CONSTRAINT METHODS ===#
@api.constrains('authorize_payment_method_type')
def _check_payment_method_type(self):
for acquirer in self.filtered(lambda acq: acq.provider == "authorize"):
@@ -49,6 +51,18 @@ class PaymentAcquirer(models.Model):
"method type on the duplicated acquirer."
))
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'authorize').update({
'support_manual_capture': True,
'support_tokenization': True,
})
# === ONCHANGE METHODS ===#
@api.onchange('authorize_payment_method_type')
def _onchange_authorize_payment_method_type(self):
if self.authorize_payment_method_type == 'bank_account':
@@ -65,6 +79,8 @@ class PaymentAcquirer(models.Model):
'payment.payment_icon_cc_visa',
)])]
# === ACTION METHODS ===#
def action_update_merchant_details(self):
""" Fetch the merchant details to update the client key and the account currency. """
self.ensure_one()
@@ -90,6 +106,8 @@ class PaymentAcquirer(models.Model):
self.authorize_currency_id = currency
self.authorize_client_key = res_content.get('publicClientKey')
# === BUSINESS METHODS ===#
@api.model
def _get_compatible_acquirers(self, *args, currency_id=None, **kwargs):
""" Override of payment to unlist Authorize acquirers for unsupported currencies. """
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_buckaroo" model="payment.acquirer">
<field name="provider">buckaroo</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_buckaroo" model="account.payment.method">
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_mollie" model="payment.acquirer">
<field name="provider">mollie</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_mollie" model="account.payment.method">
@@ -4,11 +4,7 @@
<record id="payment.payment_acquirer_ogone" model="payment.acquirer">
<field name="provider">ogone</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_tokenization">True</field>
<field name="allow_tokenization">True</field>
<field name="support_refund"></field>
</record>
<record id="payment_method_ogone" model="account.payment.method">
@@ -31,6 +31,17 @@ class PaymentAcquirer(models.Model):
ogone_shakey_out = fields.Char(
string="SHA Key OUT", required_if_provider='ogone', groups='base.group_system')
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'ogone').update({
'support_tokenization': True,
})
#=== BUSINESS METHODS ===#
@api.model
def _get_compatible_acquirers(self, *args, is_validation=False, **kwargs):
""" Override of payment to unlist Ogone acquirers for validation operations. """
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_paypal" model="payment.acquirer">
<field name="provider">paypal</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">True</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_paypal" model="account.payment.method">
@@ -24,6 +24,17 @@ class PaymentAcquirer(models.Model):
paypal_use_ipn = fields.Boolean(
string="Use IPN", help="Paypal Instant Payment Notification", default=True)
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'paypal').update({
'support_fees': True,
})
#=== BUSINESS METHODS ===#
@api.model
def _get_compatible_acquirers(self, *args, currency_id=None, **kwargs):
""" Override of payment to unlist PayPal acquirers when the currency is not supported. """
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_payulatam" model="payment.acquirer">
<field name="provider">payulatam</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_payulatam" model="account.payment.method">
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_payumoney" model="payment.acquirer">
<field name="provider">payumoney</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_payumoney" model="account.payment.method">
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_sips" model="payment.acquirer">
<field name="provider">sips</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
</record>
<record id="payment_method_sips" model="account.payment.method">
@@ -3,10 +3,6 @@
<record id="payment.payment_acquirer_stripe" model="payment.acquirer">
<field name="provider">stripe</field>
<field name="support_authorization">True</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">True</field>
<field name="allow_tokenization">True</field>
</record>
@@ -34,6 +34,16 @@ class PaymentAcquirer(models.Model):
"authenticate the messages sent from Stripe to Odoo.",
groups='base.group_system')
#=== COMPUTE METHODS ===#
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'stripe').update({
'support_manual_capture': True,
'support_tokenization': True,
})
#=== CONSTRAINT METHODS ===#
@api.constrains('state', 'stripe_publishable_key', 'stripe_secret_key')
@@ -4,10 +4,6 @@
<record id="payment.payment_acquirer_test" model="payment.acquirer">
<field name="provider">test</field>
<field name="inline_form_view_id" ref="inline_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">True</field>
<field name="allow_tokenization">True</field>
</record>
@@ -9,6 +9,8 @@ class PaymentAcquirer(models.Model):
provider = fields.Selection(selection_add=[('test', 'Test')], ondelete={'test': 'set default'})
#=== COMPUTE METHODS ===#
@api.depends('provider')
def _compute_view_configuration_fields(self):
""" Override of payment to hide the credentials page.
@@ -18,6 +20,15 @@ class PaymentAcquirer(models.Model):
super()._compute_view_configuration_fields()
self.filtered(lambda acq: acq.provider == 'test').show_credentials_page = False
def _compute_feature_support_fields(self):
""" Override of `payment` to enable additional features. """
super()._compute_feature_support_fields()
self.filtered(lambda acq: acq.provider == 'test').update({
'support_tokenization': True,
})
# === CONSTRAINT METHODS ===#
@api.constrains('state', 'provider')
def _check_acquirer_state(self):
if self.filtered(lambda a: a.provider == 'test' and a.state not in ('test', 'disabled')):
@@ -5,10 +5,6 @@
<field name="provider">transfer</field>
<field name="state">enabled</field>
<field name="redirect_form_view_id" ref="redirect_form"/>
<field name="support_authorization">False</field>
<field name="support_fees_computation">False</field>
<field name="support_refund"></field>
<field name="support_tokenization">False</field>
<!-- Clear the default value to trigger the computation of the message -->
<field name="pending_msg" eval="False"/>
</record>
@@ -19,7 +19,7 @@ class PaymentAcquirer(models.Model):
:return: None
"""
super()._compute_view_configuration_fields()
self.filtered(lambda acq: acq.provider == 'transfer').write({
self.filtered(lambda acq: acq.provider == 'transfer').update({
'show_credentials_page': False,
'show_payment_icon_ids': False,
'show_pre_msg': False,