Coverage for functions \ flipdare \ payments \ data \ payment_event_context.py: 91%

46 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-05-08 12:22 +1000

1#!/usr/bin/env python 

2# Copyright (c) 2026 Flipdare Pty Ltd. All rights reserved. 

3# 

4# This file is part of Flipdare's proprietary software and contains 

5# confidential and copyrighted material. Unauthorised copying, 

6# modification, distribution, or use of this file is strictly 

7# prohibited without prior written permission from Flipdare Pty Ltd. 

8# 

9# This software includes third-party components licensed under MIT, 

10# BSD, and Apache 2.0 licences. See THIRD_PARTY_NOTICES for details. 

11# 

12from datetime import datetime 

13 

14from flipdare.generated.shared.payment.payment_event_status import PaymentEventStatus 

15from flipdare.util.time_util import FirestoreTime 

16from flipdare.wrapper.payment.payment_event_wrapper import PaymentEventWrapper 

17 

18 

19class PaymentEventContext: 

20 __slots__ = ("_amount", "_events") 

21 

22 def __init__(self, amount: int, events: list[PaymentEventWrapper]) -> None: 

23 self._amount = amount 

24 self._events = events 

25 

26 @property 

27 def capture_complete(self) -> bool: 

28 return self._amount == self.total_amount_captured 

29 

30 @property 

31 def refund_complete(self) -> bool: 

32 return self._amount == self.total_amount_refunded 

33 

34 @property 

35 def transfer_complete(self) -> bool: 

36 return self._amount == self.total_amount_transferred 

37 

38 @property 

39 def captured_on(self) -> datetime | None: 

40 # get the last captured event with a non-zero amount_captured 

41 captured_events = [ 

42 event 

43 for event in self._events 

44 if event.status == PaymentEventStatus.CAPTURED and event.result.amount_captured > 0 

45 ] 

46 if not captured_events: 

47 return None 

48 

49 # events are ordered by timestamp ascending, so the last one is the most recent capture 

50 # so we find the last event with a non-zero amount_captured and return its timestamp 

51 last_captured_event = captured_events[-1] 

52 return FirestoreTime.from_firestore(last_captured_event.created_at) 

53 

54 @property 

55 def transferrable_amount(self) -> int: 

56 return ( 

57 self.total_amount_captured - self.total_app_fee_amount - self.total_stripe_fee_amount 

58 ) 

59 

60 @property 

61 def refundable_amount(self) -> int: 

62 return ( 

63 self._amount 

64 - self.total_amount_captured 

65 - self.total_amount_transferred 

66 - self.total_amount_refunded 

67 ) 

68 

69 @property 

70 def total_app_fee_amount(self) -> int: 

71 return sum(event.result.app_fee_amount for event in self._events) 

72 

73 @property 

74 def total_stripe_fee_amount(self) -> int: 

75 return sum(event.result.stripe_fee_amount for event in self._events) 

76 

77 @property 

78 def total_amount_captured(self) -> int: 

79 return sum( 

80 event.result.amount_captured 

81 for event in self._events 

82 if event.status == PaymentEventStatus.CAPTURED 

83 ) 

84 

85 @property 

86 def total_amount_refunded(self) -> int: 

87 return sum( 

88 event.result.amount_refunded 

89 for event in self._events 

90 if event.status == PaymentEventStatus.REFUNDED 

91 ) 

92 

93 @property 

94 def total_amount_transferred(self) -> int: 

95 return sum( 

96 event.result.amount_transferred 

97 for event in self._events 

98 if event.status == PaymentEventStatus.TRANSFERRED 

99 )