Coverage for functions \ flipdare \ generated \ model \ backend \ user_summary_entry_model.py: 81%

128 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-05-08 12:22 +1000

1#!/usr/bin/env python 

2# 

3# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved. 

4# 

5# This file is part of Flipdare's proprietary software and contains 

6# confidential and copyrighted material. Unauthorised copying, 

7# modification, distribution, or use of this file is strictly 

8# prohibited without prior written permission from Flipdare Pty Ltd. 

9# 

10# This software includes third-party components licensed under MIT, 

11# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details. 

12# 

13# NOTE: THIS FILE IS AUTO GENERATED. DO NOT EDIT. 

14# 

15# Generated by codegen_models.py 

16# 

17# Modify 'codegen_models.py' 

18# and re-run the script above to update. 

19# 

20from __future__ import annotations 

21from datetime import datetime 

22from google.cloud.firestore_v1.transforms import Sentinel 

23from flipdare.core.firestore_field import FirestoreField 

24from flipdare.util.time_util import FirestoreTime 

25from typing import Any, TypedDict, cast, Unpack 

26from enum import StrEnum 

27from pydantic import Field, ConfigDict, TypeAdapter 

28from flipdare.firestore.core.app_base_model import AppBaseModel 

29from flipdare.generated.shared.backend.summary_email_entry_type import SummaryEmailEntryType 

30from flipdare.generated.shared.backend.summary_email_category import SummaryEmailCategory 

31from flipdare.generated.model.internal.image_model import ImageModel, ImageDict 

32 

33 

34class UserSummaryEntryKeys(StrEnum): 

35 ID = "id" 

36 CREATED_AT = "created_at" 

37 UPDATED_AT = "updated_at" 

38 OBJ_ID = "obj_id" 

39 ENTRY_TYPE = "entry_type" 

40 CATEGORY = "category" 

41 FROM_NAME = "from_name" 

42 IMAGE = "image" 

43 TO_NAME = "to_name" 

44 GROUP_NAME = "group_name" 

45 MEMBER_NAME = "member_name" 

46 PLEDGE_AMOUNT = "pledge_amount" 

47 TOTAL_AMOUNT = "total_amount" 

48 DESCRIPTION = "description" 

49 ACCEPTED_NAME = "accepted_name" 

50 

51 

52# !! IMPORTANT !! 

53# !! 

54# !! this should only be used in the database to query. 

55# !! 

56class UserSummaryEntryInternalKeys(StrEnum): 

57 CREATED_AT = "created_at" 

58 UPDATED_AT = "updated_at" 

59 

60 

61class UserSummaryEntryModel(AppBaseModel): 

62 """Represents a user summary email.""" 

63 

64 model_config = ConfigDict(populate_by_name=True, arbitrary_types_allowed=True) 

65 

66 id: str | None = Field(None, alias="id") 

67 created_at: FirestoreField = Field( 

68 default_factory=cast("Any", lambda: FirestoreTime.server_timestamp()) 

69 ) 

70 updated_at: FirestoreField = Field( 

71 default_factory=cast("Any", lambda: FirestoreTime.server_timestamp()) 

72 ) 

73 obj_id: str | None = None 

74 entry_type: SummaryEmailEntryType 

75 category: SummaryEmailCategory 

76 from_name: str 

77 image: ImageModel | None = None 

78 to_name: str | None = None 

79 group_name: str | None = None 

80 member_name: str | None = None 

81 pledge_amount: int | None = None 

82 total_amount: int | None = None 

83 description: str | None = None 

84 accepted_name: str | None = None 

85 

86 @classmethod 

87 def validate_partial(cls, **data: Unpack[UserSummaryEntryDict]) -> dict[str, Any]: 

88 """ 

89 Uses Unpack to give you autocomplete and static warnings 

90 if you pass an invalid key or type in your code. 

91 

92 Returns a dict with Firestore field names (aliases) for use with batch.update(). 

93 """ 

94 result: dict[str, Any] = {} 

95 for k, v in data.items(): 

96 if k in cls.__pydantic_fields__: 

97 field_info = cls.__pydantic_fields__[k] 

98 validated_value = cast( 

99 "Any", 

100 TypeAdapter(field_info.annotation).validate_python(v), 

101 ) 

102 # Use alias if defined, otherwise use field name 

103 output_key = field_info.alias or k 

104 result[output_key] = validated_value 

105 return result 

106 

107 # ---- Convenience factories ----------------------------------------- 

108 @classmethod 

109 def create_friend_request( 

110 cls, 

111 from_name: str, 

112 from_uid: str, 

113 to_name: str, 

114 is_accepted: bool, 

115 from_avatar: ImageModel | None = None, 

116 ) -> UserSummaryEntryModel: 

117 entry_type: SummaryEmailEntryType 

118 actual_from_name: str 

119 actual_to_name: str 

120 if is_accepted: 

121 entry_type = SummaryEmailEntryType.FRIEND_REQUEST_ACCEPTED 

122 actual_from_name = to_name 

123 actual_to_name = from_name 

124 else: 

125 entry_type = SummaryEmailEntryType.FRIEND_REQUEST 

126 actual_from_name = from_name 

127 actual_to_name = to_name 

128 

129 return cls( 

130 id=None, 

131 entry_type=entry_type, 

132 category=SummaryEmailCategory.FRIEND, 

133 from_name=actual_from_name, 

134 image=from_avatar, 

135 obj_id=from_uid, 

136 to_name=actual_to_name, 

137 ) 

138 

139 @classmethod 

140 def create_count( 

141 cls, 

142 from_name: str, 

143 entry_type: SummaryEmailEntryType, 

144 from_avatar: ImageModel, 

145 ) -> UserSummaryEntryModel: 

146 if entry_type not in [ 

147 SummaryEmailEntryType.NEW_LIKE, 

148 SummaryEmailEntryType.NEW_VIEW, 

149 SummaryEmailEntryType.NEW_FOLLOWER, 

150 ]: 

151 msg = f"Invalid entry_type for create_count: {entry_type}" 

152 raise ValueError(msg) 

153 

154 return cls( 

155 id=None, 

156 entry_type=entry_type, 

157 category=SummaryEmailCategory.FRIEND, 

158 from_name=from_name, 

159 image=from_avatar, 

160 ) 

161 

162 @classmethod 

163 def create_group_request( 

164 cls, 

165 owner_name: str, 

166 group_name: str, 

167 obj_id: str, 

168 avatar: ImageModel, 

169 member_name: str, 

170 short_description: str, 

171 is_accepted: bool, 

172 ) -> UserSummaryEntryModel: 

173 entry_type: SummaryEmailEntryType 

174 from_name: str 

175 to_name: str 

176 

177 if is_accepted: 

178 entry_type = SummaryEmailEntryType.GROUP_REQUEST_ACCEPTED 

179 from_name = member_name 

180 to_name = owner_name 

181 else: 

182 entry_type = SummaryEmailEntryType.GROUP_REQUEST 

183 from_name = owner_name 

184 to_name = member_name 

185 

186 return cls( 

187 id=None, 

188 entry_type=entry_type, 

189 category=SummaryEmailCategory.GROUP, 

190 from_name=from_name, 

191 image=avatar, 

192 obj_id=obj_id, 

193 to_name=to_name, 

194 group_name=group_name, 

195 description=short_description, 

196 ) 

197 

198 @classmethod 

199 def create_dare( 

200 cls, 

201 from_name: str, 

202 to_name: str, 

203 obj_id: str, 

204 short_description: str, 

205 entry_type: SummaryEmailEntryType, 

206 avatar: ImageModel | None = None, 

207 ) -> UserSummaryEntryModel: 

208 if entry_type not in [ 

209 SummaryEmailEntryType.DARE_REQUEST, 

210 SummaryEmailEntryType.DARE_ACCEPTED, 

211 SummaryEmailEntryType.DARE_COMPLETED, 

212 ]: 

213 msg = f"Invalid entry_type for create_dare: {entry_type}" 

214 raise ValueError(msg) 

215 

216 return cls( 

217 id=None, 

218 entry_type=entry_type, 

219 category=SummaryEmailCategory.DARE, 

220 from_name=from_name, 

221 to_name=to_name, 

222 image=avatar, 

223 obj_id=obj_id, 

224 description=short_description, 

225 ) 

226 

227 @classmethod 

228 def create_group_dare( 

229 cls, 

230 owner_name: str, 

231 group_name: str, 

232 obj_id: str, 

233 avatar: ImageModel, 

234 short_description: str, 

235 entry_type: SummaryEmailEntryType, 

236 member_name: str | None = None, 

237 accepted_name: str | None = None, 

238 ) -> UserSummaryEntryModel: 

239 if entry_type not in [ 

240 SummaryEmailEntryType.GROUP_DARE_SENT, 

241 SummaryEmailEntryType.GROUP_DARE_ACCEPTED, 

242 SummaryEmailEntryType.GROUP_DARE_COMPLETED, 

243 ]: 

244 msg = f"Invalid entry_type for create_group_dare: {entry_type}" 

245 raise ValueError(msg) 

246 

247 if ( 

248 entry_type 

249 in ( 

250 SummaryEmailEntryType.GROUP_DARE_ACCEPTED, 

251 SummaryEmailEntryType.GROUP_DARE_COMPLETED, 

252 ) 

253 and accepted_name is None 

254 ): 

255 msg = "accepted_name should not be None for ACCEPTED/COMPLETED email type" 

256 raise ValueError(msg) 

257 

258 return cls( 

259 id=None, 

260 entry_type=entry_type, 

261 category=SummaryEmailCategory.GROUP, 

262 from_name=owner_name, 

263 image=avatar, 

264 obj_id=obj_id, 

265 to_name=member_name, 

266 group_name=group_name, 

267 description=short_description, 

268 accepted_name=accepted_name, 

269 ) 

270 

271 @classmethod 

272 def create_pledge_received( 

273 cls, 

274 from_name: str, 

275 obj_id: str, 

276 from_avatar: ImageModel, 

277 pledge_amount: int, 

278 total_amount: int, 

279 short_description: str, 

280 is_failed: bool, 

281 ) -> UserSummaryEntryModel: 

282 entry_type: SummaryEmailEntryType 

283 if is_failed: 

284 entry_type = SummaryEmailEntryType.PLEDGE_FAILED 

285 else: 

286 entry_type = SummaryEmailEntryType.PLEDGE_PROCESSED 

287 

288 return cls( 

289 id=None, 

290 entry_type=entry_type, 

291 category=SummaryEmailCategory.PLEDGE, 

292 from_name=from_name, 

293 image=from_avatar, 

294 obj_id=obj_id, 

295 pledge_amount=pledge_amount, 

296 total_amount=total_amount, 

297 description=short_description, 

298 ) 

299 

300 @classmethod 

301 def create_pledge_sent( 

302 cls, 

303 from_name: str, 

304 obj_id: str, 

305 from_avatar: ImageModel, 

306 pledge_amount: int, 

307 total_amount: int, 

308 short_description: str, 

309 is_complete: bool, 

310 ) -> UserSummaryEntryModel: 

311 entry_type: SummaryEmailEntryType 

312 if is_complete: 

313 entry_type = SummaryEmailEntryType.PLEDGE_PAYMENT_COMPLETE 

314 else: 

315 entry_type = SummaryEmailEntryType.PLEDGE_PAYMENT_NOTICE 

316 

317 return cls( 

318 id=None, 

319 entry_type=entry_type, 

320 category=SummaryEmailCategory.PLEDGE, 

321 from_name=from_name, 

322 image=from_avatar, 

323 obj_id=obj_id, 

324 pledge_amount=pledge_amount, 

325 total_amount=total_amount, 

326 description=short_description, 

327 ) 

328 

329 

330USERSUMMARYENTRY_FIELD_NAMES: list[str] = list(UserSummaryEntryModel.model_fields.keys()) 

331 

332 

333class UserSummaryEntryDict(TypedDict, total=False): 

334 id: str | None 

335 created_at: Sentinel | datetime | str 

336 updated_at: Sentinel | datetime | str 

337 obj_id: str | None 

338 entry_type: SummaryEmailEntryType 

339 category: SummaryEmailCategory 

340 from_name: str 

341 image: ImageDict | None 

342 to_name: str | None 

343 group_name: str | None 

344 member_name: str | None 

345 pledge_amount: int | None 

346 total_amount: int | None 

347 description: str | None 

348 accepted_name: str | None