Coverage for dibbler / queries / current_interest.py: 65%

22 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-12 13:57 +0000

1from datetime import datetime 

2 

3from sqlalchemy import BindParameter, bindparam, select 

4from sqlalchemy.orm import Session 

5 

6from dibbler.models import Transaction, TransactionType 

7from dibbler.models.Transaction import DEFAULT_INTEREST_RATE_PERCENT 

8from dibbler.queries.query_helpers import until_filter 

9 

10 

11def current_interest( 

12 sql_session: Session, 

13 until_time: BindParameter[datetime] | datetime | None = None, 

14 until_transaction: BindParameter[Transaction] | Transaction | None = None, 

15 until_inclusive: bool = True, 

16) -> int: 

17 """ 

18 Get the current interest rate percentage as of a given time or transaction. 

19 

20 Returns the interest rate percentage as an integer. 

21 """ 

22 

23 if not (until_time is None or until_transaction is None): 23 ↛ 24line 23 didn't jump to line 24 because the condition on line 23 was never true

24 raise ValueError("Cannot filter by both until_time and until_transaction.") 

25 

26 if isinstance(until_time, datetime): 26 ↛ 27line 26 didn't jump to line 27 because the condition on line 26 was never true

27 until_time = BindParameter("until_time", value=until_time) 

28 

29 if isinstance(until_transaction, Transaction): 29 ↛ 30line 29 didn't jump to line 30 because the condition on line 29 was never true

30 if until_transaction.id is None: 

31 raise ValueError("until_transaction must be persisted in the database.") 

32 until_transaction_id = bindparam("until_transaction_id", value=until_transaction.id) 

33 else: 

34 until_transaction_id = None 

35 

36 result = sql_session.scalars( 

37 select(Transaction) 

38 .where( 

39 Transaction.type_ == TransactionType.ADJUST_INTEREST, 

40 until_filter( 

41 until_time=until_time, 

42 until_transaction_id=until_transaction_id, 

43 until_inclusive=until_inclusive, 

44 ), 

45 ) 

46 .order_by(Transaction.time.desc()) 

47 .limit(1) 

48 ).one_or_none() 

49 

50 if result is None: 

51 return DEFAULT_INTEREST_RATE_PERCENT 

52 elif result.interest_rate_percent is None: 52 ↛ 53line 52 didn't jump to line 53 because the condition on line 52 was never true

53 return DEFAULT_INTEREST_RATE_PERCENT 

54 else: 

55 return result.interest_rate_percent