Coverage for polar/models/payment_method.py: 88%
24 statements
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
« prev ^ index » next coverage.py v7.15.2, created at 2026-10-07 12:42 +0000
1from typing import TYPE_CHECKING, Any
2from uuid import UUID
4from sqlalchemy import ForeignKey, String, UniqueConstraint, Uuid
5from sqlalchemy.dialects.postgresql import JSONB
6from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship
8from polar.enums import PaymentProcessor
9from polar.kit.db.models import RecordModel
10from polar.kit.extensions.sqlalchemy.types import StrEnumType
12if TYPE_CHECKING: 12 ↛ 13line 12 didn't jump to line 13 because the condition on line 12 was never true
13 from .customer import Customer
16class PaymentMethod(RecordModel):
17 __tablename__ = "payment_methods"
18 __table_args__ = (UniqueConstraint("processor", "processor_id", "customer_id"),)
20 processor: Mapped[PaymentProcessor] = mapped_column(
21 StrEnumType(PaymentProcessor), index=True, nullable=False
22 )
23 processor_id: Mapped[str] = mapped_column(String, index=True, nullable=False)
24 type: Mapped[str] = mapped_column(String, index=True, nullable=False)
25 method_metadata: Mapped[dict[str, Any]] = mapped_column(
26 JSONB, nullable=False, default=dict
27 )
29 customer_id: Mapped[UUID] = mapped_column(
30 Uuid,
31 ForeignKey("customers.id", ondelete="cascade"),
32 nullable=False,
33 index=True,
34 )
36 @declared_attr
37 def customer(cls) -> Mapped["Customer"]:
38 return relationship(
39 "Customer",
40 lazy="raise",
41 back_populates="payment_methods",
42 foreign_keys=[cls.customer_id], # type: ignore
43 )
45 @property
46 def fingerprint(self) -> str | None:
47 return self.method_metadata.get("fingerprint")