Coverage for polar/models/downloadable.py: 100%
30 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 datetime import datetime
2from enum import StrEnum
3from uuid import UUID
5from sqlalchemy import (
6 TIMESTAMP,
7 ForeignKey,
8 Integer,
9 String,
10 UniqueConstraint,
11 Uuid,
12)
13from sqlalchemy.orm import Mapped, declared_attr, mapped_column, relationship
15from polar.kit.db.models import RecordModel
17from .benefit import Benefit
18from .customer import Customer
19from .file import File
22class DownloadableStatus(StrEnum):
23 granted = "granted"
24 revoked = "revoked"
27class Downloadable(RecordModel):
28 __tablename__ = "downloadables"
29 __table_args__ = (UniqueConstraint("customer_id", "file_id", "benefit_id"),)
31 file_id: Mapped[UUID] = mapped_column(
32 Uuid, ForeignKey("files.id"), nullable=False, index=True
33 )
35 @declared_attr
36 def file(cls) -> Mapped[File]:
37 return relationship(File, lazy="raise")
39 status: Mapped[DownloadableStatus] = mapped_column(String, nullable=False)
41 customer_id: Mapped[UUID] = mapped_column(
42 Uuid,
43 ForeignKey("customers.id", ondelete="cascade"),
44 nullable=False,
45 # Don't create an index for customer_id
46 # as it's covered by the unique constraint, being the leading column of it
47 index=False,
48 )
50 @declared_attr
51 def customer(cls) -> Mapped[Customer]:
52 return relationship("Customer", lazy="raise")
54 benefit_id: Mapped[UUID] = mapped_column(
55 Uuid,
56 ForeignKey("benefits.id", ondelete="cascade"),
57 nullable=False,
58 index=True,
59 )
61 @declared_attr
62 def benefit(cls) -> Mapped[Benefit]:
63 return relationship("Benefit", lazy="raise")
65 downloaded: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
67 last_downloaded_at: Mapped[datetime | None] = mapped_column(
68 TIMESTAMP(timezone=True),
69 nullable=True,
70 )