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
« 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
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
19class PaymentEventContext:
20 __slots__ = ("_amount", "_events")
22 def __init__(self, amount: int, events: list[PaymentEventWrapper]) -> None:
23 self._amount = amount
24 self._events = events
26 @property
27 def capture_complete(self) -> bool:
28 return self._amount == self.total_amount_captured
30 @property
31 def refund_complete(self) -> bool:
32 return self._amount == self.total_amount_refunded
34 @property
35 def transfer_complete(self) -> bool:
36 return self._amount == self.total_amount_transferred
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
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)
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 )
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 )
69 @property
70 def total_app_fee_amount(self) -> int:
71 return sum(event.result.app_fee_amount for event in self._events)
73 @property
74 def total_stripe_fee_amount(self) -> int:
75 return sum(event.result.stripe_fee_amount for event in self._events)
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 )
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 )
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 )