Coverage for polar/models/issue_reward.py: 59%
41 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 16:17 +0000
« prev ^ index » next coverage.py v7.10.6, created at 2025-12-05 16:17 +0000
1from decimal import Decimal 1ab
2from typing import TYPE_CHECKING 1ab
3from uuid import UUID 1ab
5from sqlalchemy import BigInteger, ForeignKey, String, UniqueConstraint, Uuid 1ab
6from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship 1ab
8from polar.kit.db.models import RecordModel 1ab
9from polar.models.organization import Organization 1ab
10from polar.models.user import User 1ab
12if TYPE_CHECKING: 12 ↛ 13line 12 didn't jump to line 13 because the condition on line 12 was never true1ab
13 from .account import Account
14 from .pledge import Pledge
17class IssueReward(RecordModel): 1ab
18 __tablename__ = "issue_rewards" 1ab
20 __table_args__ = ( 1ab
21 UniqueConstraint("issue_reference", "github_username"),
22 UniqueConstraint("issue_reference", "organization_id"),
23 UniqueConstraint("issue_reference", "user_id"),
24 )
26 issue_reference: Mapped[str] = mapped_column(String, nullable=False, index=True) 1ab
28 # 10% == 100
29 share_thousands: Mapped[int] = mapped_column(BigInteger, nullable=False) 1ab
31 github_username: Mapped[str | None] = mapped_column( 1ab
32 String, nullable=True, default=None
33 )
35 organization_id: Mapped[UUID | None] = mapped_column( 1ab
36 Uuid, ForeignKey("organizations.id"), nullable=True, default=None, index=True
37 )
39 user_id: Mapped[UUID | None] = mapped_column( 1ab
40 Uuid, ForeignKey("users.id"), nullable=True, default=None
41 )
43 @declared_attr 1ab
44 def organization(cls) -> Mapped[Organization]: 1ab
45 return relationship( 1ab
46 Organization,
47 lazy="raise",
48 )
50 @declared_attr 1ab
51 def user(cls) -> Mapped[User]: 1ab
52 return relationship(User, lazy="raise") 1ab
54 @property 1ab
55 def pct(self) -> Decimal: 1ab
56 # Use decimal to avoid binary floating point issues
57 return Decimal(self.share_thousands) / 1000
59 def get_share_amount(self, pledge: "Pledge") -> int: 1ab
60 return round(pledge.amount * self.pct)
62 def get_rewarded(self) -> "Organization | User | None": 1ab
63 if self.organization is not None:
64 return self.organization
65 elif self.user is not None:
66 return self.user
67 return None
69 def get_rewarded_account(self) -> "Account | None": 1ab
70 rewarded = self.get_rewarded()
71 if rewarded is not None:
72 return rewarded.account
73 return None