Coverage for polar/benefit/strategies/base/schemas.py: 91%
40 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
3from pydantic import UUID4, Field, computed_field
4from pydantic.json_schema import SkipJsonSchema
6from polar.kit.metadata import MetadataInputMixin, MetadataOutputMixin
7from polar.kit.schemas import IDSchema, Schema, TimestampedSchema
8from polar.models.benefit import BenefitType
9from polar.models.benefit_grant import BenefitGrantError
10from polar.organization.schemas import OrganizationID, OrganizationPublicBase
12BENEFIT_DESCRIPTION_MIN_LENGTH = 3
13BENEFIT_DESCRIPTION_MAX_LENGTH = 42
16class BenefitProperties(Schema): ... 16 ↛ 19line 16 didn't jump to line 19 because
19class BenefitCreateBase(MetadataInputMixin, Schema):
20 type: BenefitType
21 description: str = Field(
22 ...,
23 min_length=BENEFIT_DESCRIPTION_MIN_LENGTH,
24 max_length=BENEFIT_DESCRIPTION_MAX_LENGTH,
25 description=(
26 "The description of the benefit. "
27 "Will be displayed on products having this benefit."
28 ),
29 )
30 organization_id: OrganizationID | None = Field(
31 None,
32 description=(
33 "The ID of the organization owning the benefit. "
34 "**Required unless you use an organization token.**"
35 ),
36 )
39class BenefitUpdateBase(MetadataInputMixin, Schema):
40 description: str | None = Field(
41 None,
42 min_length=BENEFIT_DESCRIPTION_MIN_LENGTH,
43 max_length=BENEFIT_DESCRIPTION_MAX_LENGTH,
44 description=(
45 "The description of the benefit. "
46 "Will be displayed on products having this benefit."
47 ),
48 )
51class BenefitPublicBase(TimestampedSchema, IDSchema):
52 id: UUID4 = Field(..., description="The ID of the benefit.")
53 type: BenefitType = Field(..., description="The type of the benefit.")
54 description: str = Field(..., description="The description of the benefit.")
55 selectable: bool = Field(
56 ..., description="Whether the benefit is selectable when creating a product."
57 )
58 deletable: bool = Field(..., description="Whether the benefit is deletable.")
59 organization_id: UUID4 = Field(
60 ..., description="The ID of the organization owning the benefit."
61 )
64class BenefitBase(MetadataOutputMixin, BenefitPublicBase): ... 64 ↛ 67line 64 didn't jump to line 67 because
67class BenefitGrantBase(IDSchema, TimestampedSchema):
68 """
69 A grant of a benefit to a customer.
70 """
72 id: UUID4 = Field(description="The ID of the grant.")
73 granted_at: datetime | None = Field(
74 None,
75 description=(
76 "The timestamp when the benefit was granted. "
77 "If `None`, the benefit is not granted."
78 ),
79 )
80 is_granted: bool = Field(description="Whether the benefit is granted.")
81 revoked_at: datetime | None = Field(
82 None,
83 description=(
84 "The timestamp when the benefit was revoked. "
85 "If `None`, the benefit is not revoked."
86 ),
87 )
88 is_revoked: bool = Field(description="Whether the benefit is revoked.")
89 subscription_id: UUID4 | None = Field(
90 description="The ID of the subscription that granted this benefit.",
91 )
92 order_id: UUID4 | None = Field(
93 description="The ID of the order that granted this benefit."
94 )
95 customer_id: UUID4 = Field(
96 description="The ID of the customer concerned by this grant."
97 )
98 benefit_id: UUID4 = Field(
99 description="The ID of the benefit concerned by this grant."
100 )
101 error: BenefitGrantError | None = Field(
102 None,
103 description="The error information if the benefit grant failed with an unrecoverable error.",
104 )
106 @computed_field(deprecated="Use `customer_id`.")
107 def user_id(self) -> SkipJsonSchema[UUID4]:
108 return self.customer_id
111class BenefitSubscriberOrganization(OrganizationPublicBase): ... 111 ↛ 114line 111 didn't jump to line 114 because
114class BenefitSubscriberBase(BenefitBase):
115 organization: BenefitSubscriberOrganization