Coverage for functions \ flipdare \ payments \ dto \ account_create_dto.py: 87%
54 statements
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
« prev ^ index » next coverage.py v7.13.0, created at 2026-05-08 12:22 +1000
1#!/usr/bin/env python
2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved.
3#
4# This file is part of Flipdare's proprietary software and contains
5# confidential and copyrighted material. Unauthorised copying,
6# modification, distribution, or use of this file is strictly
7# prohibited without prior written permission from Flipdare Pty Ltd.
8#
9# This software includes third-party components licensed under MIT,
10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details.
11#
12from stripe.params.v2.core import AccountCreateParams, AccountUpdateParams
13from flipdare.app_log import LOG
14from flipdare.generated.shared.stripe.stripe_country_code import StripeCountryCode
15from flipdare.generated.shared.stripe.stripe_currency_code import StripeCurrencyCode
16from flipdare.payments.core.stripe_account_params import StripeAccountParams
18__all__ = ["AccountCreateDTO"]
21class AccountCreateDTO:
22 __slots__ = (
23 "country_code",
24 "currency_code",
25 "email",
26 "is_express",
27 "test_clock",
28 "tokens",
29 "uid",
30 )
32 def __init__(
33 self,
34 uid: str,
35 is_express: bool,
36 email: str,
37 tokens: tuple[str, str],
38 country_code: StripeCountryCode,
39 currency_code: StripeCurrencyCode,
40 test_clock: str | None = None,
41 ) -> None:
42 self.uid = uid
43 self.is_express = is_express
44 self.email = email
45 self.tokens = tokens
46 self.country_code = country_code
47 self.currency_code = currency_code
48 self.test_clock = test_clock
50 @property
51 def first_name(self) -> str:
52 return self.tokens[0]
54 @property
55 def last_name(self) -> str:
56 return self.tokens[1]
58 def create_params(self) -> AccountCreateParams:
59 """
60 Set the team doc for info on how this account is setup (and why)
61 """
62 email = self.email
63 tokens = self.tokens
64 country_code = self.country_code
65 currency_code = self.currency_code
66 is_express = self.is_express
67 test_clock = self.test_clock
68 first_name = self.first_name
69 last_name = self.last_name
71 if not is_express:
72 # PARKED: Stripe Standard accounts are complex, but may be required in the future.
73 msg = f"Stripe standard accounts not supported, resetting to express for account {self.uid}"
74 LOG().error(msg)
75 is_express = True
77 account_params = StripeAccountParams.from_tokens(
78 uid=self.uid,
79 email=email,
80 tokens=tokens,
81 )
83 params: AccountCreateParams = {
84 "contact_email": email,
85 "display_name": account_params.display_name,
86 "identity": {
87 "entity_type": "individual",
88 "country": country_code.value,
89 # NOTE: v2 uses given_name/family_name, not first_name/last_name
90 "individual": {
91 "email": email,
92 "given_name": first_name,
93 "surname": last_name,
94 "relationship": {
95 "owner": True,
96 },
97 },
98 "business_details": {
99 "registered_name": account_params.registered_name,
100 },
101 },
102 "configuration": {
103 "merchant": {
104 "capabilities": {
105 "card_payments": {"requested": True},
106 },
107 "mcc": account_params.default_mcc,
108 "statement_descriptor": {
109 "descriptor": account_params.statement_descriptor,
110 "prefix": account_params.statement_prefix,
111 },
112 "support": {
113 "email": account_params.support_email,
114 "url": account_params.support_url,
115 },
116 },
117 "recipient": {
118 "capabilities": {
119 "stripe_balance": {"stripe_transfers": {"requested": True}},
120 },
121 },
122 # Add customer configuration
123 "customer": {
124 "shipping": {
125 "address": {
126 "country": country_code.value,
127 },
128 "name": f"{first_name} {last_name}",
129 },
130 "billing": {
131 "invoice": {
132 "prefix": account_params.invoice_prefix,
133 },
134 },
135 },
136 },
137 # # "full" = standard: connected account owns its dashboard,
138 # # fees, and losses (vs "express" where the platform owns them)
139 "dashboard": "express" if is_express else "full",
140 "defaults": {
141 "currency": currency_code.stripe_code,
142 "responsibilities": {
143 # NOTE: 7/5/26 - Too difficult to use 'stripe' for Standard accounts.
144 # NOTE: - Difficult to manage customers connected to accounts.
145 # NOTE: - Cant use the Platform Pricing tool (avoiding complex fee estimation and refund handling).
146 # NOTE: - Easier to manage refunds.
147 # NOTE: - Although now the platform is responsible for disputes..
148 # NOTE: - We have incorporated delayed transfers increase refund flexibility
149 # NOTE: and reduce risk of loss for the platform.
150 # Must be "application" for Express
151 "fees_collector": "application" if is_express else "stripe",
152 # Must be "application" for Express
153 "losses_collector": "application" if is_express else "stripe",
154 },
155 "profile": {
156 "business_url": account_params.business_url,
157 "product_description": account_params.product_description,
158 },
159 },
160 "include": [
161 "configuration.merchant",
162 "configuration.customer", # Ensure customer is included
163 "identity",
164 "defaults",
165 ],
166 }
167 if test_clock is not None:
168 params["configuration"]["customer"]["test_clock"] = test_clock
169 return params
171 def upgrade_params(self) -> AccountUpdateParams:
172 """
173 Set the team doc for info on how this account is setup (and why)
174 """
175 email = self.email
176 first_name = self.first_name
177 last_name = self.last_name
178 country_code = self.country_code
179 currency_code = self.currency_code
180 is_express = self.is_express
182 if not is_express:
183 # PARKED: Stripe Standard accounts are complex, but may be required in the future.
184 msg = f"Stripe standard accounts not supported, resetting to express for account {self.uid}"
185 LOG().error(msg)
186 is_express = True
188 account_params = StripeAccountParams.from_tokens(
189 uid=self.uid,
190 email=email,
191 tokens=(first_name, last_name),
192 )
194 params: AccountUpdateParams = {
195 "contact_email": email,
196 "display_name": account_params.display_name,
197 "identity": {
198 "entity_type": "individual",
199 "country": country_code.value,
200 "individual": {
201 "email": email,
202 "given_name": first_name,
203 "surname": last_name,
204 "relationship": {
205 "owner": True,
206 },
207 },
208 "business_details": {
209 "registered_name": account_params.registered_name,
210 },
211 },
212 "configuration": {
213 "merchant": {
214 "capabilities": {
215 "card_payments": {"requested": True},
216 },
217 "mcc": account_params.default_mcc,
218 "statement_descriptor": {
219 "descriptor": account_params.statement_descriptor,
220 "prefix": account_params.statement_prefix,
221 },
222 "support": {
223 "email": account_params.support_email,
224 "url": account_params.support_url,
225 },
226 },
227 "recipient": {
228 "capabilities": {
229 "stripe_balance": {"stripe_transfers": {"requested": True}},
230 },
231 },
232 "customer": {
233 "shipping": {
234 "address": {
235 "country": country_code.value,
236 },
237 "name": f"{first_name} {last_name}",
238 },
239 "billing": {
240 "invoice": {
241 "prefix": account_params.invoice_prefix,
242 },
243 },
244 },
245 },
246 "dashboard": "express" if is_express else "full",
247 "defaults": {
248 "currency": currency_code.stripe_code,
249 "responsibilities": {
250 "fees_collector": "application",
251 "losses_collector": "application",
252 },
253 "profile": {
254 "business_url": account_params.business_url,
255 "product_description": account_params.product_description,
256 },
257 },
258 "include": [
259 "configuration.merchant",
260 "configuration.customer",
261 "identity",
262 "defaults",
263 ],
264 }
266 return params