collab: Add billing_subscriptions table (#15448)

This PR adds a new `billing_subscriptions` table to the database, as
well as some accompanying models/queries.

In this table we store a minimal amount of data from Stripe:

- The Stripe customer ID
- The Stripe subscription ID
- The status of the Stripe subscription

This should be enough for interactions with the Stripe API (e.g., to
[create a customer portal
session](https://docs.stripe.com/api/customer_portal/sessions/create)),
as well as determine whether a subscription is active (based on the
`status`).

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-07-29 14:32:13 -04:00 committed by GitHub
parent 0702ed5cd6
commit 085d41b121
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 215 additions and 0 deletions

View file

@ -0,0 +1,55 @@
use crate::db::billing_subscription::StripeSubscriptionStatus;
use super::*;
#[derive(Debug)]
pub struct CreateBillingSubscriptionParams {
pub user_id: UserId,
pub stripe_customer_id: String,
pub stripe_subscription_id: String,
pub stripe_subscription_status: StripeSubscriptionStatus,
}
impl Database {
/// Creates a new billing subscription.
pub async fn create_billing_subscription(
&self,
params: &CreateBillingSubscriptionParams,
) -> Result<()> {
self.transaction(|tx| async move {
billing_subscription::Entity::insert(billing_subscription::ActiveModel {
user_id: ActiveValue::set(params.user_id),
stripe_customer_id: ActiveValue::set(params.stripe_customer_id.clone()),
stripe_subscription_id: ActiveValue::set(params.stripe_subscription_id.clone()),
stripe_subscription_status: ActiveValue::set(params.stripe_subscription_status),
..Default::default()
})
.exec_without_returning(&*tx)
.await?;
Ok(())
})
.await
}
/// Returns all of the active billing subscriptions for the user with the specified ID.
pub async fn get_active_billing_subscriptions(
&self,
user_id: UserId,
) -> Result<Vec<billing_subscription::Model>> {
self.transaction(|tx| async move {
let subscriptions = billing_subscription::Entity::find()
.filter(
billing_subscription::Column::UserId.eq(user_id).and(
billing_subscription::Column::StripeSubscriptionStatus
.eq(StripeSubscriptionStatus::Active),
),
)
.all(&*tx)
.await?;
Ok(subscriptions)
})
.await
}
}