Skip to content
This repository was archived by the owner on Jun 13, 2025. It is now read-only.

Commit 02cfe7f

Browse files
add end to end ach items
1 parent 058e85f commit 02cfe7f

File tree

5 files changed

+48
-4
lines changed

5 files changed

+48
-4
lines changed

api/internal/owner/serializers.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,17 @@ class StripeCardSerializer(serializers.Serializer):
108108
last4 = serializers.CharField()
109109

110110

111+
class StripeUSBankAccountSerializer(serializers.Serializer):
112+
account_holder_type = serializers.CharField()
113+
account_type = serializers.CharField()
114+
bank_name = serializers.CharField()
115+
last4 = serializers.CharField()
116+
routing_number = serializers.CharField()
117+
118+
111119
class StripePaymentMethodSerializer(serializers.Serializer):
112120
card = StripeCardSerializer(read_only=True)
121+
us_bank_account = StripeUSBankAccountSerializer(read_only=True)
113122
billing_details = serializers.JSONField(read_only=True)
114123

115124

api/internal/owner/views.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ def update_email(self, request, *args, **kwargs):
8585
raise ValidationError(detail="No new_email sent")
8686
owner = self.get_object()
8787
billing = BillingService(requesting_user=request.current_owner)
88-
billing.update_email_address(owner, new_email)
88+
should_propagate = request.data.get("should_propagate_to_payment_methods", False)
89+
billing.update_email_address(owner, new_email, should_propagate_to_payment_methods=should_propagate)
8990
return Response(self.get_serializer(owner).data)
9091

9192
@action(detail=False, methods=["patch"])

billing/views.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ def customer_subscription_created(self, subscription: stripe.Subscription) -> No
312312
self._log_updated([owner])
313313

314314
def customer_subscription_updated(self, subscription: stripe.Subscription) -> None:
315+
print("CUSTOMER SUBSCRIPTION UPDATED", subscription)
315316
owners: QuerySet[Owner] = Owner.objects.filter(
316317
stripe_subscription_id=subscription.id,
317318
stripe_customer_id=subscription.customer,
@@ -408,6 +409,8 @@ def customer_subscription_updated(self, subscription: stripe.Subscription) -> No
408409
)
409410

410411
def customer_updated(self, customer: stripe.Customer) -> None:
412+
print("CUSTOMER UPDATED", customer)
413+
411414
new_default_payment_method = customer["invoice_settings"][
412415
"default_payment_method"
413416
]

graphql_api/types/invoice/invoice.graphql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ type Card {
4343
last4: String
4444
}
4545

46+
type BankAccount {
47+
accountHolderType: String
48+
accountType: String
49+
bankName: String
50+
last4: String
51+
routingNumber: String
52+
}
53+
4654
type BillingDetails {
4755
address: Address
4856
email: String

services/billing.py

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ def update_payment_method(self, owner: Owner, payment_method):
601601
)
602602

603603
@_log_stripe_error
604-
def update_email_address(self, owner: Owner, email_address: str):
604+
def update_email_address(self, owner: Owner, email_address: str, should_propagate_to_payment_methods: bool = False):
605605
if not re.fullmatch(r"[^@]+@[^@]+\.[^@]+", email_address):
606606
return None
607607

@@ -616,6 +616,29 @@ def update_email_address(self, owner: Owner, email_address: str):
616616
f"Stripe successfully updated email address for owner {owner.ownerid} by user #{self.requesting_user.ownerid}"
617617
)
618618

619+
if should_propagate_to_payment_methods:
620+
try:
621+
default_payment_method = stripe.Customer.retrieve(
622+
owner.stripe_customer_id
623+
).invoice_settings.default_payment_method
624+
625+
stripe.PaymentMethod.modify(
626+
default_payment_method,
627+
billing_details={"email": email_address},
628+
)
629+
630+
stripe.Customer.modify(owner.stripe_customer_id, address=billing_address)
631+
log.info(
632+
f"Stripe successfully updated billing email for payment method {default_payment_method}"
633+
)
634+
except Exception:
635+
log.error(
636+
"Unable to update billing email for payment method",
637+
extra=dict(
638+
payment_method=default_payment_method,
639+
),
640+
)
641+
619642
@_log_stripe_error
620643
def update_billing_address(self, owner: Owner, name, billing_address):
621644
log.info(f"Stripe update billing address for owner {owner.ownerid}")
@@ -786,14 +809,14 @@ def update_payment_method(self, owner, payment_method):
786809
"""
787810
return self.payment_service.update_payment_method(owner, payment_method)
788811

789-
def update_email_address(self, owner: Owner, email_address: str):
812+
def update_email_address(self, owner: Owner, email_address: str, should_propagate_to_payment_methods: bool = False):
790813
"""
791814
Takes an owner and a new email. Email is a string coming directly from
792815
the front-end. If the owner has a payment id and if it's a valid email,
793816
the payment service will update the email address in the upstream service.
794817
Otherwise returns None.
795818
"""
796-
return self.payment_service.update_email_address(owner, email_address)
819+
return self.payment_service.update_email_address(owner, email_address, should_propagate_to_payment_methods)
797820

798821
def update_billing_address(self, owner: Owner, name: str, billing_address):
799822
"""

0 commit comments

Comments
 (0)