@@ -308,12 +308,10 @@ def __init__(self, tr, max_age_timestamp):
308
308
self .log = get_logger (__name__ )
309
309
self .received_detail = 0
310
310
self .requested_detail = 0
311
- self .num_timeline_details = 0
312
311
self .events_without_docs = []
313
312
self .events_with_docs = []
314
313
self .num_timelines = 0
315
314
self .timeline_events = {}
316
- self .timeline_events_iter = None
317
315
self .max_age_timestamp = max_age_timestamp
318
316
319
317
async def get_next_timeline_transactions (self , response = None ):
@@ -329,24 +327,24 @@ async def get_next_timeline_transactions(self, response=None):
329
327
await self .tr .timeline_transactions ()
330
328
else :
331
329
self .num_timelines += 1
332
- # print(json.dumps(response))
333
- self .num_timeline_details += len (response ['items' ])
330
+ added_last_event = True
334
331
for event in response ['items' ]:
335
- event ['source' ] = "timelineTransaction"
336
- self .timeline_events [event ['id' ]] = event
332
+ if self .max_age_timestamp == 0 or datetime .fromisoformat (event ['timestamp' ][:19 ]).timestamp () >= self .max_age_timestamp :
333
+ event ['source' ] = "timelineTransaction"
334
+ self .timeline_events [event ['id' ]] = event
335
+ else :
336
+ added_last_event = False
337
+ break
337
338
338
- after = response ['cursors' ].get ('after' )
339
-
340
- last_transaction_time = response ['items' ][- 1 ]['timestamp' ][:19 ]
341
- timestamp = datetime .fromisoformat (last_transaction_time ).timestamp ()
342
339
self .log .info (
343
- f'Received #{ self .num_timelines :<2} timeline transactions until { last_transaction_time } '
340
+ f'Received #{ self .num_timelines :<2} timeline transactions'
344
341
)
345
- if (after is not None ) and ((self .max_age_timestamp == 0 ) or (timestamp >= self .max_age_timestamp )):
342
+ after = response ['cursors' ].get ('after' )
343
+ if (after is not None ) and added_last_event :
346
344
self .log .info (
347
345
f'Subscribing #{ self .num_timelines + 1 :<2} timeline transactions'
348
346
)
349
- await self .tr .timeline_transactions (after )
347
+ await self .tr .timeline_transactions (after )
350
348
else :
351
349
# last timeline is reached
352
350
self .log .info ('Received last relevant timeline transaction' )
@@ -365,19 +363,21 @@ async def get_next_timeline_activity_log(self, response=None):
365
363
self .num_timelines = 0
366
364
await self .tr .timeline_activity_log ()
367
365
else :
368
- last_transaction_time = response ['items' ][- 1 ]['timestamp' ][:19 ]
369
- timestamp = datetime .fromisoformat (last_transaction_time ).timestamp ()
370
366
self .num_timelines += 1
371
- # print(json.dumps(response))
372
- self .num_timeline_details += len (response ['items' ])
367
+ added_last_event = True
373
368
for event in response ['items' ]:
374
- if event ['id' ] not in self .timeline_events :
369
+ if self .max_age_timestamp == 0 or datetime .fromisoformat (event ['timestamp' ][:19 ]).timestamp () >= self .max_age_timestamp :
370
+ if event ['id' ] in self .timeline_events :
371
+ self .log .warning (f"Received duplicate event { event ['id' ] } " )
375
372
event ['source' ] = "timelineActivity"
376
373
self .timeline_events [event ['id' ]] = event
374
+ else :
375
+ added_last_event = False
376
+ break
377
377
378
+ self .log .info (f'Received #{ self .num_timelines :<2} timeline activity log' )
378
379
after = response ['cursors' ].get ('after' )
379
- self .log .info (f'Received #{ self .num_timelines :<2} timeline activity log unitl { last_transaction_time } ' )
380
- if (after is not None ) and ((self .max_age_timestamp == 0 ) or (timestamp >= self .max_age_timestamp )):
380
+ if (after is not None ) and added_last_event :
381
381
self .log .info (
382
382
f'Subscribing #{ self .num_timelines + 1 :<2} timeline activity log'
383
383
)
@@ -393,9 +393,9 @@ async def _get_timeline_details(self):
393
393
for event in self .timeline_events .values ():
394
394
action = event .get ('action' )
395
395
msg = ''
396
- timestamp_field = datetime .fromisoformat (event ['timestamp' ][:19 ]).timestamp ()
396
+ timestamp_field = datetime .fromisoformat (event ['timestamp' ][:19 ]).timestamp ()
397
397
if self .max_age_timestamp != 0 and (timestamp_field < self .max_age_timestamp ):
398
- msg += 'Skip: too old'
398
+ continue
399
399
elif action is None :
400
400
if event .get ('actionLabel' ) is None :
401
401
msg += 'Skip: no action'
@@ -404,51 +404,47 @@ async def _get_timeline_details(self):
404
404
elif action .get ('payload' ) != event ['id' ]:
405
405
msg += f"Skip: payload unmatched ({ action ['payload' ]} )"
406
406
407
- if msg == '' :
408
- self .events_with_docs .append (event )
409
- else :
407
+ if msg != '' :
410
408
self .events_without_docs .append (event )
411
- self .log .debug (f"{ msg } { event ['title' ]} : { event .get ('body' )} { json .dumps (event )} " )
412
- self .num_timeline_details -= 1
413
- continue
414
-
415
- self .requested_detail += 1
416
- await self .tr .timeline_detail_v2 (event ['id' ])
409
+ self .log .debug (f"{ msg } { event ['title' ]} : { event .get ('body' )} " )
410
+ else :
411
+ self .requested_detail += 1
412
+ await self .tr .timeline_detail_v2 (event ['id' ])
417
413
self .log .info ('All timeline details requested' )
418
414
return False
419
415
420
- async def timelineDetail (self , response , dl ):
416
+ async def process_timelineDetail (self , response , dl ):
421
417
'''
422
- process timeline response and request timelines
418
+ process timeline details response
419
+ download any associated docs
420
+ create other_events.json, events_with_documents.json and account_transactions.csv
423
421
'''
424
422
425
423
self .received_detail += 1
426
424
event = self .timeline_events [response ['id' ]]
427
425
event ['details' ] = response
428
426
429
- is_savings_plan = (event ["eventType" ] == "SAVINGS_PLAN_EXECUTED" )
430
-
431
- max_details_digits = len (str (self .num_timeline_details ))
427
+ max_details_digits = len (str (self .requested_detail ))
432
428
self .log .info (
433
- f"{ self .received_detail :>{max_details_digits }} /{ self .num_timeline_details } : "
434
- + f"{ event ['title' ]} -- { event ['subtitle' ]} "
429
+ f"{ self .received_detail :>{max_details_digits }} /{ self .requested_detail } : "
430
+ + f"{ event ['title' ]} -- { event ['subtitle' ]} - { event [ 'timestamp' ][: 19 ] } "
435
431
)
436
432
437
- if is_savings_plan :
438
- subfolder = 'Sparplan'
439
- else :
440
- subfolder = {
433
+ subfolder = {
441
434
'benefits_saveback_execution' : 'Saveback' ,
442
435
'benefits_spare_change_execution' : 'RoundUp' ,
443
436
'ssp_corporate_action_invoice_cash' : 'Dividende' ,
444
437
'CREDIT' : 'Dividende' ,
445
438
'INTEREST_PAYOUT_CREATED' : 'Zinsen' ,
439
+ "SAVINGS_PLAN_EXECUTED" :'Sparplan'
446
440
}.get (event ["eventType" ])
447
441
442
+ event ['has_docs' ] = False
448
443
for section in response ['sections' ]:
449
444
if section ['type' ] != 'documents' :
450
445
continue
451
446
for doc in section ['data' ]:
447
+ event ['has_docs' ] = True
452
448
try :
453
449
timestamp = datetime .strptime (doc ['detail' ], '%d.%m.%Y' ).timestamp ()
454
450
except (ValueError , KeyError ):
@@ -459,7 +455,12 @@ async def timelineDetail(self, response, dl):
459
455
title += f" - { event ['subtitle' ]} "
460
456
dl .dl_doc (doc , title , doc .get ('detail' ), subfolder )
461
457
462
- if self .received_detail == self .num_timeline_details :
458
+ if event ['has_docs' ]:
459
+ self .events_with_docs .append (event )
460
+ else :
461
+ self .events_without_docs .append (event )
462
+
463
+ if self .received_detail == self .requested_detail :
463
464
self .log .info ('Received all details' )
464
465
dl .output_path .mkdir (parents = True , exist_ok = True )
465
466
with open (dl .output_path / 'other_events.json' , 'w' , encoding = 'utf-8' ) as f :
0 commit comments