billing_subscription.rs

  1use crate::db::{BillingCustomerId, BillingSubscriptionId};
  2use sea_orm::entity::prelude::*;
  3use serde::Serialize;
  4
  5/// A billing subscription.
  6#[derive(Clone, Debug, Default, PartialEq, Eq, DeriveEntityModel)]
  7#[sea_orm(table_name = "billing_subscriptions")]
  8pub struct Model {
  9    #[sea_orm(primary_key)]
 10    pub id: BillingSubscriptionId,
 11    pub billing_customer_id: BillingCustomerId,
 12    pub kind: Option<SubscriptionKind>,
 13    pub stripe_subscription_id: String,
 14    pub stripe_subscription_status: StripeSubscriptionStatus,
 15    pub stripe_cancel_at: Option<DateTime>,
 16    pub stripe_cancellation_reason: Option<StripeCancellationReason>,
 17    pub stripe_current_period_start: Option<i64>,
 18    pub stripe_current_period_end: Option<i64>,
 19    pub created_at: DateTime,
 20}
 21
 22impl Model {
 23    pub fn current_period_start_at(&self) -> Option<DateTimeUtc> {
 24        let period_start = self.stripe_current_period_start?;
 25        chrono::DateTime::from_timestamp(period_start, 0)
 26    }
 27
 28    pub fn current_period_end_at(&self) -> Option<DateTimeUtc> {
 29        let period_end = self.stripe_current_period_end?;
 30        chrono::DateTime::from_timestamp(period_end, 0)
 31    }
 32}
 33
 34#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
 35pub enum Relation {
 36    #[sea_orm(
 37        belongs_to = "super::billing_customer::Entity",
 38        from = "Column::BillingCustomerId",
 39        to = "super::billing_customer::Column::Id"
 40    )]
 41    BillingCustomer,
 42}
 43
 44impl Related<super::billing_customer::Entity> for Entity {
 45    fn to() -> RelationDef {
 46        Relation::BillingCustomer.def()
 47    }
 48}
 49
 50impl ActiveModelBehavior for ActiveModel {}
 51
 52#[derive(Eq, PartialEq, Copy, Clone, Debug, EnumIter, DeriveActiveEnum, Hash, Serialize)]
 53#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
 54#[serde(rename_all = "snake_case")]
 55pub enum SubscriptionKind {
 56    #[sea_orm(string_value = "zed_pro")]
 57    ZedPro,
 58    #[sea_orm(string_value = "zed_pro_trial")]
 59    ZedProTrial,
 60    #[sea_orm(string_value = "zed_free")]
 61    ZedFree,
 62}
 63
 64/// The status of a Stripe subscription.
 65///
 66/// [Stripe docs](https://docs.stripe.com/api/subscriptions/object#subscription_object-status)
 67#[derive(
 68    Eq, PartialEq, Copy, Clone, Debug, EnumIter, DeriveActiveEnum, Default, Hash, Serialize,
 69)]
 70#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
 71#[serde(rename_all = "snake_case")]
 72pub enum StripeSubscriptionStatus {
 73    #[default]
 74    #[sea_orm(string_value = "incomplete")]
 75    Incomplete,
 76    #[sea_orm(string_value = "incomplete_expired")]
 77    IncompleteExpired,
 78    #[sea_orm(string_value = "trialing")]
 79    Trialing,
 80    #[sea_orm(string_value = "active")]
 81    Active,
 82    #[sea_orm(string_value = "past_due")]
 83    PastDue,
 84    #[sea_orm(string_value = "canceled")]
 85    Canceled,
 86    #[sea_orm(string_value = "unpaid")]
 87    Unpaid,
 88    #[sea_orm(string_value = "paused")]
 89    Paused,
 90}
 91
 92impl StripeSubscriptionStatus {
 93    pub fn is_cancelable(&self) -> bool {
 94        match self {
 95            Self::Trialing | Self::Active | Self::PastDue => true,
 96            Self::Incomplete
 97            | Self::IncompleteExpired
 98            | Self::Canceled
 99            | Self::Unpaid
100            | Self::Paused => false,
101        }
102    }
103}
104
105/// The cancellation reason for a Stripe subscription.
106///
107/// [Stripe docs](https://docs.stripe.com/api/subscriptions/object#subscription_object-cancellation_details-reason)
108#[derive(Eq, PartialEq, Copy, Clone, Debug, EnumIter, DeriveActiveEnum, Hash, Serialize)]
109#[sea_orm(rs_type = "String", db_type = "String(StringLen::None)")]
110#[serde(rename_all = "snake_case")]
111pub enum StripeCancellationReason {
112    #[sea_orm(string_value = "cancellation_requested")]
113    CancellationRequested,
114    #[sea_orm(string_value = "payment_disputed")]
115    PaymentDisputed,
116    #[sea_orm(string_value = "payment_failed")]
117    PaymentFailed,
118}