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

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 

17 

18__all__ = ["AccountCreateDTO"] 

19 

20 

21class AccountCreateDTO: 

22 __slots__ = ( 

23 "country_code", 

24 "currency_code", 

25 "email", 

26 "is_express", 

27 "test_clock", 

28 "tokens", 

29 "uid", 

30 ) 

31 

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 

49 

50 @property 

51 def first_name(self) -> str: 

52 return self.tokens[0] 

53 

54 @property 

55 def last_name(self) -> str: 

56 return self.tokens[1] 

57 

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 

70 

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 

76 

77 account_params = StripeAccountParams.from_tokens( 

78 uid=self.uid, 

79 email=email, 

80 tokens=tokens, 

81 ) 

82 

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 

170 

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 

181 

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 

187 

188 account_params = StripeAccountParams.from_tokens( 

189 uid=self.uid, 

190 email=email, 

191 tokens=(first_name, last_name), 

192 ) 

193 

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 } 

265 

266 return params