@@ -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+
203276def 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