Skip to content

Commit fc4cfd4

Browse files
authored
Merge pull request #51 from ebastos/main
Move more formatting to dedicated functions
2 parents 712270e + 0810836 commit fc4cfd4

1 file changed

Lines changed: 86 additions & 50 deletions

File tree

ws_api/formatters.py

Lines changed: 86 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,79 @@ def _format_credit_card_description(act: dict) -> bool:
200200
return False
201201

202202

203+
def _format_internal_transfer(act: dict, api_context) -> bool:
204+
"""Format description for internal transfer activities."""
205+
if act["type"] not in ("INTERNAL_TRANSFER", "ASSET_MOVEMENT"):
206+
return False
207+
208+
accounts = api_context.get_accounts(False)
209+
matching = [acc for acc in accounts if acc["id"] == act["opposingAccountId"]]
210+
target_account = matching.pop() if matching else None
211+
account_description = (
212+
f"{target_account['description']} ({target_account['number']})"
213+
if target_account
214+
else act["opposingAccountId"]
215+
)
216+
direction = "to" if act["subType"] == "SOURCE" else "from"
217+
act["description"] = (
218+
f"Money transfer: {direction} Wealthsimple {account_description}"
219+
)
220+
return True
221+
222+
223+
def _format_trade(act: dict, api_context) -> bool:
224+
"""Format description for trade activities."""
225+
if act["type"] not in (
226+
"DIY_BUY",
227+
"DIY_SELL",
228+
"MANAGED_BUY",
229+
"MANAGED_SELL",
230+
"CRYPTO_BUY",
231+
"CRYPTO_SELL",
232+
):
233+
return False
234+
235+
if "MANAGED" in act["type"]:
236+
verb = "Managed transaction"
237+
else:
238+
verb = act["subType"].replace("_", " ").capitalize()
239+
if "CRYPTO" in act["type"]:
240+
verb = f"Crypto {verb}"
241+
action = "buy" if "_BUY" in act["type"] else "sell"
242+
security = api_context.security_id_to_symbol(act["securityId"])
243+
if act["assetQuantity"] is None:
244+
act["description"] = f"{verb}: {action} TBD"
245+
else:
246+
act["description"] = (
247+
f"{verb}: {action} {float(act['assetQuantity'])} x "
248+
f"{security} @ {float(act['amount']) / float(act['assetQuantity'])}"
249+
)
250+
return True
251+
252+
253+
def _format_eft(act: dict, api_context) -> bool:
254+
"""Format description for EFT activities."""
255+
if act["subType"] != "EFT":
256+
return False
257+
258+
details = api_context.get_etf_details(act["externalCanonicalId"])
259+
type_ = act["type"].lower().capitalize()
260+
direction = "from" if act["type"] == "DEPOSIT" else "to"
261+
prop = "source" if act["type"] == "DEPOSIT" else "destination"
262+
bank_account_info = {}
263+
if isinstance(details, dict):
264+
bank_account_info = details.get(prop, {})
265+
bank_account = {}
266+
if isinstance(bank_account_info, dict):
267+
bank_account = bank_account_info.get("bankAccount", {})
268+
nickname = bank_account.get("nickname")
269+
account_number = bank_account.get("accountNumber")
270+
if not nickname:
271+
nickname = bank_account.get("accountName")
272+
act["description"] = f"{type_}: EFT {direction} {nickname} {account_number}"
273+
return True
274+
275+
203276
def format_activity_description(act: dict, api_context) -> None:
204277
"""Add human-readable description to an activity dict.
205278
@@ -215,30 +288,27 @@ def format_activity_description(act: dict, api_context) -> None:
215288
"""
216289
act["description"] = f"{act['type']}: {act['subType']}"
217290

218-
if _format_corporate_action_subdivision(act, api_context) or _format_institutional_transfer(act, api_context) or _format_credit_card_description(act):
291+
if (
292+
_format_corporate_action_subdivision(act, api_context)
293+
or _format_institutional_transfer(act, api_context)
294+
or _format_credit_card_description(act)
295+
or _format_internal_transfer(act, api_context)
296+
or _format_trade(act, api_context)
297+
or _format_eft(act, api_context)
298+
):
219299
pass # Handled by helper function
220300

221-
elif act["type"] == "INTERNAL_TRANSFER" or act["type"] == "ASSET_MOVEMENT":
222-
accounts = api_context.get_accounts(False)
223-
matching = [acc for acc in accounts if acc["id"] == act["opposingAccountId"]]
224-
target_account = matching.pop() if matching else None
225-
account_description = (
226-
f"{target_account['description']} ({target_account['number']})"
227-
if target_account
228-
else act["opposingAccountId"]
229-
)
230-
direction = "to" if act["subType"] == "SOURCE" else "from"
301+
elif act["type"] == "LEGACY_INTERNAL_TRANSFER":
231302
act["description"] = (
232-
f"Money transfer: {direction} Wealthsimple {account_description}"
303+
"Transfer in" if act["subType"] == "DESTINATION" else "Transfer out"
233304
)
234305

235-
elif act["type"] == "LEGACY_INTERNAL_TRANSFER":
236-
act["description"] = "Transfer in" if act["subType"] == "DESTINATION" else "Transfer out"
237-
238306
elif act["type"] == "CRYPTO_STAKING_ACTION":
239307
action = "stake" if act["subType"] == "STAKE" else "unstake"
240308
security = api_context.security_id_to_symbol(act["securityId"])
241-
act["description"] = f"Crypto {action}: {float(act['assetQuantity'])} x {security}"
309+
act["description"] = (
310+
f"Crypto {action}: {float(act['assetQuantity'])} x {security}"
311+
)
242312

243313
elif act["type"] == "CRYPTO_TRANSFER":
244314
action = "sent" if act["subType"] == "TRANSFER_OUT" else "received"
@@ -247,23 +317,6 @@ def format_activity_description(act: dict, api_context) -> None:
247317
f"Crypto {action}: {float(act['assetQuantity'])} x {security}"
248318
)
249319

250-
elif act["type"] in ["DIY_BUY", "DIY_SELL", "MANAGED_BUY", "MANAGED_SELL", "CRYPTO_BUY", "CRYPTO_SELL"]:
251-
if "MANAGED" in act["type"]:
252-
verb = "Managed transaction"
253-
else:
254-
verb = act["subType"].replace("_", " ").capitalize()
255-
if "CRYPTO" in act["type"]:
256-
verb = f"Crypto {verb}"
257-
action = "buy" if "_BUY" in act["type"] else "sell"
258-
security = api_context.security_id_to_symbol(act["securityId"])
259-
if act["assetQuantity"] is None:
260-
act["description"] = f"{verb}: {action} TBD"
261-
else:
262-
act["description"] = (
263-
f"{verb}: {action} {float(act['assetQuantity'])} x "
264-
f"{security} @ {float(act['amount']) / float(act['assetQuantity'])}"
265-
)
266-
267320
elif act["type"] in ["DEPOSIT", "WITHDRAWAL"] and act["subType"] in [
268321
"E_TRANSFER",
269322
"E_TRANSFER_FUNDING",
@@ -277,23 +330,6 @@ def format_activity_description(act: dict, api_context) -> None:
277330
type_ = act["type"].lower().capitalize()
278331
act["description"] = f"{type_}: Debit card funding"
279332

280-
elif act["subType"] == "EFT":
281-
details = api_context.get_etf_details(act["externalCanonicalId"])
282-
type_ = act["type"].lower().capitalize()
283-
direction = "from" if act["type"] == "DEPOSIT" else "to"
284-
prop = "source" if act["type"] == "DEPOSIT" else "destination"
285-
bank_account_info = {}
286-
if isinstance(details, dict):
287-
bank_account_info = details.get(prop, {})
288-
bank_account = {}
289-
if isinstance(bank_account_info, dict):
290-
bank_account = bank_account_info.get("bankAccount", {})
291-
nickname = bank_account.get("nickname")
292-
account_number = bank_account.get("accountNumber")
293-
if not nickname:
294-
nickname = bank_account.get("accountName")
295-
act["description"] = f"{type_}: EFT {direction} {nickname} {account_number}"
296-
297333
elif act["type"] == "REFUND" and act["subType"] == "TRANSFER_FEE_REFUND":
298334
act["description"] = "Reimbursement: account transfer fee"
299335

0 commit comments

Comments
 (0)