changeset a84c94e1d191 in modules/account_payment_stripe:default
details: 
https://hg.tryton.org/modules/account_payment_stripe?cmd=changeset&node=a84c94e1d191
description:
        Add wizard to create direct debit for configured parties

        issue10772
        review379071002
diffstat:

 __init__.py                                |    1 +
 common.py                                  |  144 +++++++++++++++++++++++
 party.py                                   |   15 ++
 party.xml                                  |   12 +
 payment.py                                 |  176 ++++++----------------------
 tryton.cfg                                 |    1 +
 view/party_reception_direct_debit_form.xml |   18 ++
 7 files changed, 233 insertions(+), 134 deletions(-)

diffs (466 lines):

diff -r 92d7812129fc -r a84c94e1d191 __init__.py
--- a/__init__.py       Mon Oct 11 18:22:19 2021 +0200
+++ b/__init__.py       Mon Oct 11 18:35:28 2021 +0200
@@ -21,6 +21,7 @@
         payment.Payment,
         payment.CustomerSourceDetachAsk,
         party.Party,
+        party.PartyReceptionDirectDebit,
         ir.Cron,
         module='account_payment_stripe', type_='model')
     Pool.register(
diff -r 92d7812129fc -r a84c94e1d191 common.py
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/common.py Mon Oct 11 18:35:28 2021 +0200
@@ -0,0 +1,144 @@
+# 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 StripeCustomerMethodMixin:
+    __slots__ = ()
+
+    stripe_account = fields.Function(fields.Many2One(
+            'account.payment.stripe.account', "Stripe Account"),
+        'on_change_with_stripe_account')
+
+    stripe_customer = fields.Many2One(
+        'account.payment.stripe.customer', "Stripe Customer",
+        domain=[
+            ('party', '=', Eval('party', -1)),
+            ('stripe_account', '=', Eval('stripe_account', -1)),
+            ],
+        states={
+            'invisible': Eval('process_method') != 'stripe',
+            'readonly': (
+                ~Eval('party') | (Eval('party', -1) < 0)
+                | ~Eval('stripe_account') | (Eval('stripe_account', -1) < 0)),
+            },
+        depends=['party', 'stripe_account', 'process_method'])
+
+    stripe_customer_source = fields.Char(
+        "Stripe Customer Source",
+        states={
+            'invisible': (
+                (Eval('process_method') != 'stripe')
+                | ~Eval('stripe_customer')
+                | Eval('stripe_customer_payment_method')),
+            },
+        depends=[
+            'process_method', 'stripe_customer',
+            'stripe_customer_payment_method'])
+    # Use Function field with selection to avoid to query Stripe
+    # to validate the value
+    stripe_customer_source_selection = fields.Function(fields.Selection(
+            'get_stripe_customer_sources', "Stripe Customer Source",
+            states={
+                'invisible': (
+                    (Eval('process_method') != 'stripe')
+                    | ~Eval('stripe_customer')
+                    | Eval('stripe_customer_payment_method')),
+                },
+            depends=[
+                'process_method', 'stripe_customer',
+                'stripe_customer_payment_method']),
+        'get_stripe_customer_source', setter='set_stripe_customer_source')
+
+    stripe_customer_payment_method = fields.Char(
+        "Stripe Payment Method",
+        states={
+            'invisible': (
+                (Eval('process_method') != 'stripe')
+                | ~Eval('stripe_customer')
+                | Eval('stripe_customer_source')),
+            },
+        depends=[
+            'process_method', 'stripe_customer', 'stripe_customer_source'])
+    # Use Function field with selection to avoid to query Stripe
+    # to validate the value
+    stripe_customer_payment_method_selection = fields.Function(
+        fields.Selection(
+            'get_stripe_customer_payment_methods',
+            "Stripe Customer Payment Method",
+            states={
+                'invisible': (
+                    (Eval('process_method') != 'stripe')
+                    | ~Eval('stripe_customer')
+                    | Eval('stripe_customer_source')),
+                },
+            depends=[
+                'process_method', 'stripe_customer',
+                'stripe_customer_source']),
+        'get_stripe_customer_payment_method',
+        setter='set_stripe_customer_payment_method')
+
+    def on_change_party(self):
+        try:
+            super().on_change_party()
+        except AttributeError:
+            pass
+        self.stripe_customer = None
+        self.stripe_customer_source = None
+        self.stripe_customer_source_selection = None
+
+    @fields.depends('journal')
+    def on_change_with_stripe_account(self, name=None):
+        if self.journal and self.journal.process_method == 'stripe':
+            return self.journal.stripe_account.id
+
+    @fields.depends('stripe_customer', 'stripe_customer_source')
+    def get_stripe_customer_sources(self):
+        sources = [('', '')]
+        if self.stripe_customer:
+            sources.extend(self.stripe_customer.sources())
+        if (self.stripe_customer_source
+                and self.stripe_customer_source not in dict(sources)):
+            sources.append(
+                (self.stripe_customer_source, self.stripe_customer_source))
+        return sources
+
+    @fields.depends(
+        'stripe_customer_source_selection',
+        'stripe_customer_source')
+    def on_change_stripe_customer_source_selection(self):
+        self.stripe_customer_source = self.stripe_customer_source_selection
+
+    def get_stripe_customer_source(self, name):
+        return self.stripe_customer_source
+
+    @classmethod
+    def set_stripe_customer_source(cls, payments, name, value):
+        pass
+
+    @fields.depends('stripe_customer', 'stripe_customer_payment_method')
+    def get_stripe_customer_payment_methods(self):
+        methods = [('', '')]
+        if self.stripe_customer:
+            methods.extend(self.stripe_customer.payment_methods())
+        if (self.stripe_customer_payment_method
+                and self.stripe_customer_payment_method not in dict(methods)):
+            methods.append(
+                (self.stripe_customer_payment_method,
+                    self.stripe_customer_payment_method))
+        return methods
+
+    @fields.depends(
+        'stripe_customer_payment_method_selection',
+        'stripe_customer_payment_method')
+    def on_change_stripe_customer_payment_method_selection(self):
+        self.stripe_customer_payment_method = (
+            self.stripe_customer_payment_method_selection)
+
+    def get_stripe_customer_payment_method(self, name):
+        return self.stripe_customer_payment_method
+
+    @classmethod
+    def set_stripe_customer_payment_method(cls, payments, name, value):
+        pass
diff -r 92d7812129fc -r a84c94e1d191 party.py
--- a/party.py  Mon Oct 11 18:22:19 2021 +0200
+++ b/party.py  Mon Oct 11 18:35:28 2021 +0200
@@ -3,6 +3,8 @@
 from trytond.pool import PoolMeta, Pool
 from trytond.model import fields
 
+from .common import StripeCustomerMethodMixin
+
 
 class Party(metaclass=PoolMeta):
     __name__ = 'party.party'
@@ -29,6 +31,19 @@
             Customer.__queue__.stripe_update(to_update)
 
 
+class PartyReceptionDirectDebit(
+        StripeCustomerMethodMixin, metaclass=PoolMeta):
+    __name__ = 'party.party.reception_direct_debit'
+
+    def _get_payment(self, line, date, amount):
+        payment = super()._get_payment(line, date, amount)
+        self.stripe_customer = self.stripe_customer
+        self.stripe_customer_source = self.stripe_customer_source
+        self.stripe_customer_payment_method = (
+            self.stripe_customer_payment_method)
+        return payment
+
+
 class Replace(metaclass=PoolMeta):
     __name__ = 'party.replace'
 
diff -r 92d7812129fc -r a84c94e1d191 party.xml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/party.xml Mon Oct 11 18:35:28 2021 +0200
@@ -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>
diff -r 92d7812129fc -r a84c94e1d191 payment.py
--- a/payment.py        Mon Oct 11 18:22:19 2021 +0200
+++ b/payment.py        Mon Oct 11 18:35:28 2021 +0200
@@ -16,7 +16,7 @@
 from trytond.model import (
     ModelSQL, ModelView, Workflow, DeactivableMixin, fields, dualmethod)
 from trytond.pool import PoolMeta, Pool
-from trytond.pyson import Eval, Bool
+from trytond.pyson import Eval
 from trytond.report import Report, get_email
 from trytond.rpc import RPC
 from trytond.sendmail import sendmail_transactional
@@ -30,6 +30,8 @@
     ProcessError, PaymentValidationError)
 from trytond.modules.currency.fields import Monetary
 
+from .common import StripeCustomerMethodMixin
+
 logger = logging.getLogger(__name__)
 stripe.max_network_retries = config.getint(
     'account_payment_stripe', 'max_network_retries', default=3)
@@ -118,7 +120,7 @@
             }
 
 
-class Payment(CheckoutMixin, metaclass=PoolMeta):
+class Payment(StripeCustomerMethodMixin, CheckoutMixin, metaclass=PoolMeta):
     __name__ = 'account.payment'
 
     stripe_checkout_needed = fields.Function(
@@ -192,76 +194,6 @@
         states={
             'invisible': ~Eval('stripe_dispute_status'),
             })
-    stripe_customer = fields.Many2One(
-        'account.payment.stripe.customer', "Stripe Customer",
-        domain=[
-            ('party', '=', Eval('party', -1)),
-            ('stripe_account', '=', Eval('stripe_account', -1)),
-            ],
-        states={
-            'invisible': Eval('process_method') != 'stripe',
-            'required': Bool(Eval('stripe_customer_source')),
-            'readonly': (~Eval('state').in_(['draft', 'approved'])
-                | Eval('stripe_token') | Eval('stripe_payment_intent_id')),
-            },
-        depends=['party', 'stripe_account', 'process_method',
-            'stripe_customer_source', 'stripe_token',
-            'stripe_payment_intent_id', 'state'])
-    stripe_customer_source = fields.Char(
-        "Stripe Customer Source",
-        states={
-            'invisible': ((Eval('process_method') != 'stripe')
-                | Eval('stripe_token')
-                | Eval('stripe_payment_intent_id')
-                | ~Eval('stripe_customer')),
-            'readonly': ~Eval('state').in_(['draft', 'approved']),
-            },
-        depends=['process_method', 'stripe_token', 'stripe_payment_intent_id',
-            'stripe_customer', 'state'])
-    # Use Function field with selection to avoid to query Stripe
-    # to validate the value
-    stripe_customer_source_selection = fields.Function(fields.Selection(
-            'get_stripe_customer_sources', "Stripe Customer Source",
-            states={
-                'invisible': ((Eval('process_method') != 'stripe')
-                    | Eval('stripe_token')
-                    | Eval('stripe_payment_intent_id')
-                    | ~Eval('stripe_customer')),
-                'readonly': ~Eval('state').in_(['draft', 'approved']),
-                },
-            depends=[
-                'process_method', 'stripe_token', 'stripe_customer', 'state']),
-        'get_stripe_customer_source', setter='set_stripe_customer_source')
-    stripe_customer_payment_method = fields.Char(
-        "Stripe Payment Method",
-        states={
-            'invisible': ((Eval('process_method') != 'stripe')
-                | Eval('stripe_token')
-                | ~Eval('stripe_customer')),
-            'readonly': (~Eval('state').in_(['draft', 'approved'])
-                | Eval('stripe_payment_intent_id')),
-            },
-        depends=['process_method', 'stripe_token', 'stripe_customer', 'state'])
-    # Use Function field with selection to avoid to query Stripe
-    # to validate the value
-    stripe_customer_payment_method_selection = fields.Function(
-        fields.Selection(
-            'get_stripe_customer_payment_methods',
-            "Stripe Customer Payment Method",
-            states={
-                'invisible': ((Eval('process_method') != 'stripe')
-                    | Eval('stripe_token')
-                    | ~Eval('stripe_customer')),
-                'readonly': (~Eval('state').in_(['draft', 'approved'])
-                    | Eval('stripe_payment_intent_id')),
-                },
-            depends=[
-                'process_method', 'stripe_token', 'stripe_customer', 'state']),
-        'get_stripe_customer_payment_method',
-        setter='set_stripe_customer_payment_method')
-    stripe_account = fields.Function(fields.Many2One(
-            'account.payment.stripe.account', "Stripe Account"),
-        'on_change_with_stripe_account')
     stripe_amount = fields.Function(
         fields.Integer("Stripe Amount"),
         'get_stripe_amount', setter='set_stripe_amount')
@@ -278,6 +210,44 @@
     @classmethod
     def __setup__(cls):
         super(Payment, cls).__setup__()
+
+        cls.stripe_customer.states['readonly'] = (
+            ~Eval('state').in_(['draft', 'approved'])
+            | Eval('stripe_token')
+            | Eval('stripe_payment_intent_id'))
+        cls.stripe_customer.depends.extend(
+            ['state', 'stripe_token', 'stripe_payment_intent_id'])
+
+        cls.stripe_customer_source.states['invisible'] |= (
+            Eval('stripe_token') | Eval('stripe_payment_intent_id'))
+        cls.stripe_customer_source.states['readonly'] = (
+            ~Eval('state').in_(['draft', 'approved']))
+        cls.stripe_customer_source.depends.extend(
+            ['stripe_token', 'stripe_payment_intent_id', 'state'])
+
+        cls.stripe_customer_source_selection.states['invisible'] |= (
+            Eval('stripe_token') | Eval('stripe_payment_intent_id'))
+        cls.stripe_customer_source_selection.states['readonly'] = (
+            ~Eval('state').in_(['draft', 'approved']))
+        cls.stripe_customer_source_selection.depends.extend(
+            ['stripe_token', 'stripe_payment_intent_id', 'state'])
+
+        cls.stripe_customer_payment_method.states['invisible'] |= (
+            Eval('stripe_token'))
+        cls.stripe_customer_payment_method.states['readonly'] = (
+            ~Eval('state').in_(['draft', 'approved'])
+            | Eval('stripe_payment_intent_id'))
+        cls.stripe_customer_payment_method.depends.extend(
+            ['stripe_token', 'state', 'stripe_payment_intent_id'])
+
+        cls.stripe_customer_payment_method_selection.states['invisible'] |= (
+            Eval('stripe_token'))
+        cls.stripe_customer_payment_method_selection.states['readonly'] = (
+            ~Eval('state').in_(['draft', 'approved'])
+            | Eval('stripe_payment_intent_id'))
+        cls.stripe_customer_payment_method_selection.depends.extend(
+            ['stripe_token', 'state', 'stripe_payment_intent_id'])
+
         cls.amount.states['readonly'] &= ~Eval('stripe_capture_needed')
         cls.amount.depends.append('stripe_capture_needed')
         cls.stripe_amount.states.update(cls.amount.states)
@@ -330,63 +300,6 @@
     def default_stripe_idempotency_key(cls):
         return uuid.uuid4().hex
 
-    @fields.depends('party')
-    def on_change_party(self):
-        super(Payment, self).on_change_party()
-        self.stripe_customer = None
-        self.stripe_customer_source = None
-        self.stripe_customer_source_selection = None
-
-    @fields.depends('stripe_customer', 'stripe_customer_source')
-    def get_stripe_customer_sources(self):
-        sources = [('', '')]
-        if self.stripe_customer:
-            sources.extend(self.stripe_customer.sources())
-        if (self.stripe_customer_source
-                and self.stripe_customer_source not in dict(sources)):
-            sources.append(
-                (self.stripe_customer_source, self.stripe_customer_source))
-        return sources
-
-    @fields.depends(
-        'stripe_customer_source_selection',
-        'stripe_customer_source')
-    def on_change_stripe_customer_source_selection(self):
-        self.stripe_customer_source = self.stripe_customer_source_selection
-
-    def get_stripe_customer_source(self, name):
-        return self.stripe_customer_source
-
-    @classmethod
-    def set_stripe_customer_source(cls, payments, name, value):
-        pass
-
-    @fields.depends('stripe_customer', 'stripe_customer_payment_method')
-    def get_stripe_customer_payment_methods(self):
-        methods = [('', '')]
-        if self.stripe_customer:
-            methods.extend(self.stripe_customer.payment_methods())
-        if (self.stripe_customer_payment_method
-                and self.stripe_customer_payment_method not in dict(methods)):
-            methods.append(
-                (self.stripe_customer_payment_method,
-                    self.stripe_customer_payment_method))
-        return methods
-
-    @fields.depends(
-        'stripe_customer_payment_method_selection',
-        'stripe_customer_payment_method')
-    def on_change_stripe_customer_payment_method_selection(self):
-        self.stripe_customer_payment_method = (
-            self.stripe_customer_payment_method_selection)
-
-    def get_stripe_customer_payment_method(self, name):
-        return self.stripe_customer_payment_method
-
-    @classmethod
-    def set_stripe_customer_payment_method(cls, payments, name, value):
-        pass
-
     @fields.depends('process_method',
         'stripe_token', 'stripe_payment_intent_id',
         'stripe_customer_source', 'stripe_customer_source_selection',
@@ -406,11 +319,6 @@
             and not self.stripe_capture
             and not self.stripe_captured)
 
-    @fields.depends('journal')
-    def on_change_with_stripe_account(self, name=None):
-        if self.journal and self.journal.process_method == 'stripe':
-            return self.journal.stripe_account.id
-
     def get_stripe_amount(self, name):
         return int(self.amount * 10 ** self.currency.digits)
 
diff -r 92d7812129fc -r a84c94e1d191 tryton.cfg
--- a/tryton.cfg        Mon Oct 11 18:22:19 2021 +0200
+++ b/tryton.cfg        Mon Oct 11 18:35:28 2021 +0200
@@ -7,4 +7,5 @@
     party
 xml:
     payment.xml
+    party.xml
     message.xml
diff -r 92d7812129fc -r a84c94e1d191 view/party_reception_direct_debit_form.xml
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ b/view/party_reception_direct_debit_form.xml        Mon Oct 11 18:35:28 
2021 +0200
@@ -0,0 +1,18 @@
+<?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="stripe_customer" string="Customer:"/>
+            <field name="stripe_customer" colspan="3"/>
+
+            <label name="stripe_customer_source_selection" string="Source:"/>
+            <field name="stripe_customer_source_selection" colspan="3"/>
+
+            <label name="stripe_customer_payment_method_selection" 
string="Payment Method:"/>
+            <field name="stripe_customer_payment_method_selection" 
colspan="3"/>
+
+            <field name="stripe_customer_source" colspan="4" invisible="1"/>
+            <field name="stripe_customer_payment_method" colspan="4" 
invisible="1"/>
+    </xpath>
+</data>

Reply via email to