From a1e56225c45a97f8ea6150e83754d1547b05da32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Krier?= Date: Sat, 26 Dec 2020 23:55:17 +0100 Subject: [PATCH] Add preferred locales and update Stripe Customer The Stripe Customer is updated each time the party is modified in such way that the parameters are also changed. We do not manage any retry on the update because it is just a best effort. issue9887 review305021002 --- CHANGELOG | 3 ++ party.py | 20 +++++++++++- payment.py | 40 +++++++++++++++++++---- tests/scenario_account_payment_stripe.rst | 15 +++++++++ 4 files changed, 71 insertions(+), 7 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b13237360b..7d647cc527 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,6 @@ +* Update Stripe Customer +* Add preferred locales to Customer + Version 5.8.0 - 2020-11-02 * Bug fixes (see mercurial logs for details) * Remove support for Python 3.5 diff --git a/party.py b/party.py index 9dd800813e..ea0d6aee4b 100644 --- a/party.py +++ b/party.py @@ -1,6 +1,6 @@ # 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.pool import PoolMeta +from trytond.pool import PoolMeta, Pool from trytond.model import fields @@ -10,6 +10,24 @@ class Party(metaclass=PoolMeta): stripe_customers = fields.One2Many( 'account.payment.stripe.customer', 'party', "Stripe Customers") + @classmethod + def write(cls, *args): + pool = Pool() + Customer = pool.get('account.payment.stripe.customer') + + parties = sum(args[0:None:2], []) + customers = sum((p.stripe_customers for p in parties), ()) + customer2params = {c: c._customer_parameters() for c in customers} + + super().write(*args) + + to_update = [] + for customer, params in customer2params.items(): + if customer._customer_parameters() != params: + to_update.append(customer) + if to_update: + Customer.__queue__.stripe_update(to_update) + class Replace(metaclass=PoolMeta): __name__ = 'party.replace' diff --git a/payment.py b/payment.py index 92b9366db4..b39002ee6a 100644 --- a/payment.py +++ b/payment.py @@ -1522,9 +1522,8 @@ class Customer(CheckoutMixin, DeactivableMixin, ModelSQL, ModelView): try: cu = stripe.Customer.create( api_key=customer.stripe_account.secret_key, - description=customer.rec_name, - email=customer.party.email, - source=customer.stripe_token) + source=customer.stripe_token, + **customer._customer_parameters()) except (stripe.error.RateLimitError, stripe.error.APIConnectionError) as e: logger.warning(str(e)) @@ -1549,6 +1548,36 @@ class Customer(CheckoutMixin, DeactivableMixin, ModelSQL, ModelView): customer.save() Transaction().commit() + def _customer_parameters(self): + locales = [pl.lang.code for pl in self.party.langs if pl.lang] + return { + 'email': self.party.email, + 'name': self.party.name, + 'phone': self.party.phone, + 'preferred_locales': locales, + } + + @classmethod + def stripe_update(cls, customers): + for customer in customers: + try: + stripe.Customer.modify( + customer.stripe_customer_id, + api_key=customer.stripe_account.secret_key, + **customer._customer_parameters() + ) + except (stripe.error.RateLimitError, + stripe.error.APIConnectionError) as e: + logger.warning(str(e)) + except Exception as e: + if (isinstance(e, stripe.error.StripeError) + and e.code in RETRY_CODES): + logger.warning(str(e)) + else: + logger.error( + "Error when updating customer %d", customer.id, + exc_info=True) + @classmethod def stripe_delete(cls, customers=None): """Delete customer @@ -1731,9 +1760,8 @@ class Customer(CheckoutMixin, DeactivableMixin, ModelSQL, ModelView): else: cu = stripe.Customer.create( api_key=customer.stripe_account.secret_key, - description=customer.rec_name, - email=customer.party.email, - payment_method=setup_intent.payment_method) + payment_method=setup_intent.payment_method, + **customer._customer_parameters()) customer.stripe_customer_id = cu.id except (stripe.error.RateLimitError, stripe.error.APIConnectionError) as e: diff --git a/tests/scenario_account_payment_stripe.rst b/tests/scenario_account_payment_stripe.rst index 8ed2b045e8..5778b59d40 100644 --- a/tests/scenario_account_payment_stripe.rst +++ b/tests/scenario_account_payment_stripe.rst @@ -73,7 +73,9 @@ Create payment journal:: Create party:: >>> Party = Model.get('party.party') + >>> Lang = Model.get('ir.lang') >>> customer = Party(name='Customer') + >>> customer.lang, = Lang.find([('code', '=', 'en')]) >>> customer.save() Create approved payment:: @@ -195,6 +197,19 @@ Run cron:: >>> bool(stripe_customer.stripe_customer_id) True +Update customer:: + + >>> contact = customer.contact_mechanisms.new() + >>> contact.type = 'email' + >>> contact.value = 'customer@example.com' + >>> customer.save() + + >>> cus = stripe.Customer.retrieve(stripe_customer.stripe_customer_id) + >>> cus.email + 'customer@example.com' + >>> cus.preferred_locales + ['en'] + Make payment with customer:: >>> payment, = payment.duplicate()