Add wizard to create direct debit for configured parties

issue10772
review379071002
This commit is contained in:
Cédric Krier committed 2021-10-11 18:35:27 +02:00
1 parent 5c29051f5a
commit 7255fc070e
7 files changed
+149 -83

No files matched your search

+1
View File
@@ -21,6 +21,7 @@ def register():
account.PaymentBraintreeCustomer,
account.PaymentBraintreeCustomerPaymentMethodDeleteAsk,
party.Party,
party.PartyReceptionDirectDebit,
module='account_payment_braintree', type_='model')
Pool.register(
account.PaymentBraintreeCustomerPaymentMethodDelete,
+23 -83
View File
@@ -25,6 +25,8 @@ from trytond.modules.account_payment.exceptions import (
ProcessError, PaymentValidationError)
from trytond.modules.currency.fields import Monetary
from .common import BraintreeCustomerMethodMixin
logger = logging.getLogger(__name__)
SUCCEEDED_STATUSES = {braintree.Transaction.Status.Settled}
@@ -149,57 +151,9 @@ class CheckoutMixin:
self.save()
class Payment(CheckoutMixin, metaclass=PoolMeta):
class Payment(CheckoutMixin, BraintreeCustomerMethodMixin, metaclass=PoolMeta):
__name__ = 'account.payment'
braintree_account = fields.Function(fields.Many2One(
'account.payment.braintree.account', "Braintree Account"),
'on_change_with_braintree_account')
braintree_customer = fields.Many2One(
'account.payment.braintree.customer', "Braintree Customer",
domain=[
('party', '=', Eval('party', -1)),
('braintree_account', '=', Eval('braintree_account', -1)),
],
states={
'invisible': Eval('process_method') != 'braintree',
'readonly': (~Eval('state').in_(['draft', 'approved'])
| Eval('braintree_nonce')),
},
depends=['party', 'braintree_account', 'process_method',
'braintree_nonce', 'state'])
braintree_customer_method = fields.Char(
"Braintree Customer Method",
states={
'invisible': ((Eval('process_method') != 'braintree')
| Eval('braintree_nonce')
| ~Eval('braintree_customer')),
'readonly': ~Eval('state').in_(['draft', 'approved']),
},
depends=[
'process_method',
'braintree_nonce',
'braintree_customer',
'state'])
# Use Function field with selection
# to avoid querying Braintree on validation
braintree_customer_method_selection = fields.Function(fields.Selection(
'get_braintree_customer_methods', "Braintree Customer Method",
states={
'invisible': ((Eval('process_method') != 'braintree')
| Eval('braintree_nonce')
| ~Eval('braintree_customer')),
'readonly': ~Eval('state').in_(['draft', 'approved']),
},
depends=[
'process_method',
'braintree_nonce',
'braintree_customer',
'state']),
'get_braintree_customer_method',
setter='set_braintree_customer_method')
braintree_transaction_id = fields.Char(
"Braintree Transaction ID", readonly=True,
states={
@@ -250,6 +204,26 @@ class Payment(CheckoutMixin, metaclass=PoolMeta):
super().__setup__()
cls.amount.states['readonly'] &= ~Eval('braintree_settlement_needed')
cls.amount.depends.append('braintree_settlement_needed')
cls.braintree_customer.states['readonly'] = (
~Eval('state').in_(['draft', 'approved'])
| Eval('braintree_nonce'))
cls.braintree_customer.depends.extend(['state', 'braintree_nonce'])
cls.braintree_customer_method.states['invisible'] |= (
Eval('braintree_nonce'))
cls.braintree_customer_method.states['readonly'] = (
~Eval('state').in_(['draft', 'approved']))
cls.braintree_customer_method.depends.extend(
['braintree_nonce', 'state'])
cls.braintree_customer_method_selection.states['invisible'] |= (
Eval('braintree_nonce'))
cls.braintree_customer_method_selection.states['readonly'] = (
~Eval('state').in_(['draft', 'approved']))
cls.braintree_customer_method_selection.depends.extend(
['braintree_nonce', 'state'])
cls._buttons.update({
'braintree_checkout': {
'invisible': (~Eval('state', 'draft').in_(
@@ -275,40 +249,6 @@ class Payment(CheckoutMixin, metaclass=PoolMeta):
},
})
@fields.depends('journal')
def on_change_with_braintree_account(self, name=None):
if self.journal and self.journal.process_method == 'braintree':
return self.journal.braintree_account.id
def on_change_party(self):
super().on_change_party()
self.braintree_customer = None
@fields.depends('braintree_customer', 'braintree_customer_method')
def get_braintree_customer_methods(self):
methods = [('', '')]
if self.braintree_customer:
methods.extend(self.braintree_customer.payment_methods())
if (self.braintree_customer_method
and self.braintree_customer_method not in dict(methods)):
methods.append((
self.braintree_customer_method,
self.braintree_customer_method))
return methods
@fields.depends(
'braintree_customer_method_selection', 'braintree_customer_method')
def on_change_braintree_customer_method_selection(self):
self.braintree_customer_method = (
self.braintree_customer_method_selection)
def get_braintree_customer_method(self, name):
return self.braintree_customer_method
@classmethod
def set_braintree_customer_method(cls, payments, name, value):
pass
@classmethod
def default_braintree_settle_payment(cls):
return True
+84
View File
@@ -0,0 +1,84 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.model import fields
from trytond.pyson import Eval
class BraintreeCustomerMethodMixin:
__slots__ = ()
braintree_account = fields.Function(fields.Many2One(
'account.payment.braintree.account', "Braintree Account"),
'on_change_with_braintree_account')
braintree_customer = fields.Many2One(
'account.payment.braintree.customer', "Braintree Customer",
domain=[
('party', '=', Eval('party', -1)),
('braintree_account', '=', Eval('braintree_account', -1)),
],
states={
'invisible': Eval('process_method') != 'braintree',
'readonly': (
~Eval('party') | (Eval('party', -1) < 0)
| ~Eval('braintree_account')
| (Eval('braintree_account', -1) < 0)),
},
depends=['party', 'process_method', 'braintree_account'])
braintree_customer_method = fields.Char(
"Braintree Customer Method",
states={
'invisible': (
(Eval('process_method') != 'braintree')
| ~Eval('braintree_customer')),
},
depends=['process_method', 'braintree_customer'])
# Use Function field with selection
# to avoid querying Braintree on validation
braintree_customer_method_selection = fields.Function(fields.Selection(
'get_braintree_customer_methods', "Braintree Customer Method",
states={
'invisible': (
(Eval('process_method') != 'braintree')
| ~Eval('braintree_customer')),
},
depends=['process_method', 'braintree_customer']),
'get_braintree_customer_method',
setter='set_braintree_customer_method')
def on_change_party(self):
try:
super().on_change_party()
except AttributeError:
pass
self.braintree_customer = None
@fields.depends('journal')
def on_change_with_braintree_account(self, name=None):
if self.journal and self.journal.process_method == 'braintree':
return self.journal.braintree_account.id
@fields.depends('braintree_customer', 'braintree_customer_method')
def get_braintree_customer_methods(self):
methods = [('', '')]
if self.braintree_customer:
methods.extend(self.braintree_customer.payment_methods())
if (self.braintree_customer_method
and self.braintree_customer_method not in dict(methods)):
methods.append((
self.braintree_customer_method,
self.braintree_customer_method))
return methods
@fields.depends(
'braintree_customer_method_selection', 'braintree_customer_method')
def on_change_braintree_customer_method_selection(self):
self.braintree_customer_method = (
self.braintree_customer_method_selection)
def get_braintree_customer_method(self, name):
return self.braintree_customer_method
@classmethod
def set_braintree_customer_method(cls, payments, name, value):
pass
+13
View File
@@ -3,6 +3,8 @@
from trytond.pool import PoolMeta, Pool
from trytond.model import fields
from .common import BraintreeCustomerMethodMixin
class Party(metaclass=PoolMeta):
__name__ = 'party.party'
@@ -29,6 +31,17 @@ class Party(metaclass=PoolMeta):
Customer.__queue__.braintree_update(to_update)
class PartyReceptionDirectDebit(
BraintreeCustomerMethodMixin, metaclass=PoolMeta):
__name__ = 'party.party.reception_direct_debit'
def _get_payment(self, line, date, amount):
payment = super()._get_payment(line, date, amount)
payment.braintree_customer = self.braintree_customer
payment.braintree_customer_method = self.braintree_customer_method
return payment
class Replace(metaclass=PoolMeta):
__name__ = 'party.replace'
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<tryton>
<data>
<record model="ir.ui.view" id="party_reception_direct_debit_view_form">
<field name="model">party.party.reception_direct_debit</field>
<field name="inherit" ref="account_payment.party_reception_direct_debit_view_form"/>
<field name="name">party_reception_direct_debit_form</field>
</record>
</data>
</tryton>
+1
View File
@@ -8,4 +8,5 @@ depends:
party
xml:
account.xml
party.xml
message.xml
@@ -0,0 +1,15 @@
<?xml version="1.0"?>
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
this repository contains the full copyright notices and license terms. -->
<data>
<xpath expr="//field[@name='currency']" position="after">
<label name="braintree_customer" string="Customer:"/>
<field name="braintree_customer" colspan="3"/>
<label name="braintree_customer_method_selection" string="Payment Method:"/>
<field name="braintree_customer_method_selection" colspan="3"/>
<field name="braintree_customer_method" colspan="4" invisible="1"/>
</xpath>
</data>