1
1
from datetime import datetime , timedelta , time as d_time
2
+ from logging import Logger
2
3
from time import time
3
4
from dateutil .relativedelta import *
4
5
import sqlalchemy
5
6
from sqlalchemy .orm import joinedload , load_only , defer
7
+ from sqlalchemy .sql import functions
8
+
6
9
from config .constants import *
7
10
from core import get_logger
8
11
from dal import db
@@ -24,18 +27,13 @@ def balances_cron():
24
27
yesterday = today - timedelta (days = 1 )
25
28
five_days_ago = yesterday - timedelta (days = 5 )
26
29
30
+ balances = Balance .query .options (joinedload ('agreement' ), joinedload ('payments' )).filter (
31
+ Balance .due_date .between (five_days_ago , yesterday ),
32
+ Balance .id .in_ (db .session .query (functions .max (Balance .id )).group_by (Balance .agreement_id ).subquery ())
33
+ )
34
+
27
35
try :
28
- agreements = RentalAgreement .query .options (
29
- joinedload ('balances' ), joinedload ('balances.payments' ), joinedload ('interval' )).filter (
30
- RentalAgreement .terminated_on .is_ (None )).filter (RentalAgreement .id .notin_ (
31
- Balance .query .options (
32
- defer (Balance .id ),
33
- load_only (Balance .agreement_id )
34
- ).filter (Balance .due_date >= today ).subquery ()))\
35
- .join (Balance ).filter (
36
- (Balance .due_date .between (five_days_ago , yesterday )))
37
-
38
- process_agreements (agreements .all (), logger , yesterday , five_days_ago )
36
+ process_agreements (balances .all (), logger , yesterday , five_days_ago )
39
37
40
38
except (sqlalchemy .exc .OperationalError , Exception ) as e :
41
39
logger .error ('^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^' )
@@ -45,57 +43,43 @@ def balances_cron():
45
43
logger .info ('Took: ' + str (timedelta (seconds = (time () - start ))))
46
44
47
45
48
- def process_agreements (agreements , logger , yesterday : datetime , five_days_ago : datetime ):
49
- from config import debug
50
- debug ()
51
-
52
- agreement : RentalAgreement
53
- for agreement in agreements :
54
- if len (agreement .balances ) > 0 :
55
-
56
- cycle_balance : Balance
57
- for cycle_balance in agreement .balances :
58
-
59
- if (cycle_balance .created_on >= five_days_ago and cycle_balance .init_processed ) or \
60
- cycle_balance .due_date <= five_days_ago or cycle_balance .due_date > yesterday :
61
-
62
- logger .info ('Skipping balance ' + str (cycle_balance .id ) + ' for aggrement ' + str (agreement .id ) +
63
- ' since it was created within the last 5 days and has been init_processed.' )
64
- continue
46
+ def process_agreements (balances : list , logger : Logger , yesterday : datetime , five_days_ago : datetime ):
47
+ # this should only contain distinct values
48
+ agreement_ids = []
49
+ cycle_balance : Balance
50
+ for cycle_balance in balances :
65
51
66
- logger . info ( 'Processing agreement id: ' + str ( agreement . id ))
52
+ assert cycle_balance . agreement_id not in agreement_ids
67
53
68
- if not cycle_balance .init_processed :
69
- cycle_balance .init_processed = True
54
+ logger .info ('Processing agreement id: ' + str (cycle_balance .agreement_id ))
70
55
71
- payments = sum (map (lambda b : b .amount , cycle_balance .payments ))
56
+ payments = sum (map (lambda b : b .amount , cycle_balance .payments ))
72
57
73
- logger .info (str (len (cycle_balance .payments )) + ' Payments processed Total:' + str (payments ))
58
+ logger .info (str (len (cycle_balance .payments )) + ' Payments processed Total:' + str (payments ))
74
59
75
- previous_balance = cycle_balance .balance - payments
76
- new_balance = previous_balance + agreement .rate
60
+ previous_balance = cycle_balance .balance - payments
61
+ new_balance = previous_balance + cycle_balance . agreement .rate
77
62
78
- logger .info ('Previous balance: ' + str (previous_balance ) + ' | New balance: ' + str (new_balance ))
63
+ logger .info ('Previous balance: ' + str (previous_balance ) + ' | New balance: ' + str (new_balance ))
79
64
80
- if agreement .interval .interval == SEMANAL :
81
- delta = timedelta (weeks = 1 )
82
- elif agreement .interval .interval == QUINCENAL :
83
- delta = timedelta (days = 14 )
84
- else :
85
- delta = relativedelta (months = 1 )
65
+ if cycle_balance . agreement .interval .interval == SEMANAL :
66
+ delta = timedelta (weeks = 1 )
67
+ elif cycle_balance . agreement .interval .interval == QUINCENAL :
68
+ delta = timedelta (days = 14 )
69
+ else :
70
+ delta = relativedelta (months = 1 )
86
71
87
- new_cycle_balance = Balance (
88
- agreement = agreement ,
89
- balance = new_balance ,
90
- previous_balance = previous_balance ,
91
- due_date = cycle_balance .due_date + delta ,
92
- init_processed = True ,
93
- )
94
- logger .info ('Agreement entered on: ' + str (agreement .entered_on ))
95
- logger .info ('Pay cycle: ' + agreement .interval .interval )
96
- logger .info ('Last due date: ' + str (cycle_balance .due_date ))
97
- logger .info ('Next due date: ' + str (new_cycle_balance .due_date ))
72
+ new_cycle_balance = Balance (
73
+ agreement = cycle_balance .agreement ,
74
+ balance = new_balance ,
75
+ previous_balance = previous_balance ,
76
+ due_date = cycle_balance .due_date + delta ,
77
+ )
78
+ logger .info ('Agreement entered on: ' + str (cycle_balance .agreement .entered_on ))
79
+ logger .info ('Pay cycle: ' + cycle_balance .agreement .interval .interval )
80
+ logger .info ('Last due date: ' + str (cycle_balance .due_date ))
81
+ logger .info ('Next due date: ' + str (new_cycle_balance .due_date ))
98
82
99
- db .session .add (new_cycle_balance )
83
+ db .session .add (new_cycle_balance )
100
84
101
85
db .session .commit ()
0 commit comments