Coverage for polar/models/processor_transaction.py: 96%
28 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 15:52 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 15:52 +0000
1import datetime 1ab
2from enum import StrEnum 1ab
3from typing import Any, Self 1ab
4from uuid import UUID 1ab
6import stripe as stripe_lib 1ab
7from sqlalchemy import TIMESTAMP, BigInteger, String, Text, Uuid 1ab
8from sqlalchemy.dialects.postgresql import JSONB 1ab
9from sqlalchemy.orm import Mapped, mapped_column 1ab
11from polar.kit.db.models import Model 1ab
12from polar.kit.extensions.sqlalchemy.types import StringEnum 1ab
13from polar.kit.utils import generate_uuid, utc_now 1ab
16class Processor(StrEnum): 1ab
17 """
18 Supported payment or payout processors, i.e rails for transactions.
19 """
21 stripe = "stripe" 1ab
24class ProcessorTransaction(Model): 1ab
25 __tablename__ = "processor_transactions" 1ab
27 id: Mapped[UUID] = mapped_column(Uuid, primary_key=True, default=generate_uuid) 1ab
28 timestamp: Mapped[datetime.datetime] = mapped_column( 1ab
29 TIMESTAMP(timezone=True), nullable=False, default=utc_now, index=True
30 )
31 processor: Mapped[Processor] = mapped_column( 1ab
32 StringEnum(Processor), index=True, nullable=False
33 )
34 processor_id: Mapped[str] = mapped_column( 1ab
35 String, nullable=False, index=True, unique=True
36 )
37 type: Mapped[str] = mapped_column(String, nullable=False, index=True) 1ab
38 currency: Mapped[str] = mapped_column(String(3), nullable=False) 1ab
39 amount: Mapped[int] = mapped_column(BigInteger, nullable=False) 1ab
40 fee: Mapped[int] = mapped_column(BigInteger, nullable=False) 1ab
41 description: Mapped[str | None] = mapped_column(Text, nullable=True) 1ab
42 raw: Mapped[dict[str, Any]] = mapped_column(JSONB, nullable=False, default=dict) 1ab
44 @classmethod 1ab
45 def from_stripe(cls, bt: stripe_lib.BalanceTransaction) -> Self: 1ab
46 return cls(
47 timestamp=datetime.datetime.fromtimestamp(bt.created, tz=datetime.UTC),
48 processor=Processor.stripe,
49 processor_id=bt.id,
50 type=bt.type,
51 currency=bt.currency,
52 amount=bt.amount,
53 fee=bt.fee,
54 description=bt.description,
55 raw=bt,
56 )