collab: Remove GET /billing/preferences endpoint (#34566)

This PR removes the `GET /billing/preferences` endpoint, as it has been
moved to `cloud.zed.dev`.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2025-07-16 13:55:01 -04:00 committed by GitHub
parent ffc69b07e5
commit 048dc47d87
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 3 additions and 140 deletions

View file

@ -1,4 +1,5 @@
use anyhow::{Context as _, bail};
use axum::routing::put;
use axum::{
Extension, Json, Router,
extract::{self, Query},
@ -27,8 +28,8 @@ use crate::api::events::SnowflakeRow;
use crate::db::billing_subscription::{
StripeCancellationReason, StripeSubscriptionStatus, SubscriptionKind,
};
use crate::llm::AGENT_EXTENDED_TRIAL_FEATURE_FLAG;
use crate::llm::db::subscription_usage_meter::{self, CompletionMode};
use crate::llm::{AGENT_EXTENDED_TRIAL_FEATURE_FLAG, DEFAULT_MAX_MONTHLY_SPEND};
use crate::rpc::{ResultExt as _, Server};
use crate::stripe_client::{
StripeCancellationDetailsReason, StripeClient, StripeCustomerId, StripeSubscription,
@ -47,10 +48,7 @@ use crate::{
pub fn router() -> Router {
Router::new()
.route(
"/billing/preferences",
get(get_billing_preferences).put(update_billing_preferences),
)
.route("/billing/preferences", put(update_billing_preferences))
.route(
"/billing/subscriptions",
get(list_billing_subscriptions).post(create_billing_subscription),
@ -66,11 +64,6 @@ pub fn router() -> Router {
.route("/billing/usage", get(get_current_usage))
}
#[derive(Debug, Deserialize)]
struct GetBillingPreferencesParams {
github_user_id: i32,
}
#[derive(Debug, Serialize)]
struct BillingPreferencesResponse {
trial_started_at: Option<String>,
@ -79,43 +72,6 @@ struct BillingPreferencesResponse {
model_request_overages_spend_limit_in_cents: i32,
}
async fn get_billing_preferences(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<GetBillingPreferencesParams>,
) -> Result<Json<BillingPreferencesResponse>> {
let user = app
.db
.get_user_by_github_user_id(params.github_user_id)
.await?
.context("user not found")?;
let billing_customer = app.db.get_billing_customer_by_user_id(user.id).await?;
let preferences = app.db.get_billing_preferences(user.id).await?;
Ok(Json(BillingPreferencesResponse {
trial_started_at: billing_customer
.and_then(|billing_customer| billing_customer.trial_started_at)
.map(|trial_started_at| {
trial_started_at
.and_utc()
.to_rfc3339_opts(SecondsFormat::Millis, true)
}),
max_monthly_llm_usage_spending_in_cents: preferences
.as_ref()
.map_or(DEFAULT_MAX_MONTHLY_SPEND.0 as i32, |preferences| {
preferences.max_monthly_llm_usage_spending_in_cents
}),
model_request_overages_enabled: preferences.as_ref().map_or(false, |preferences| {
preferences.model_request_overages_enabled
}),
model_request_overages_spend_limit_in_cents: preferences
.as_ref()
.map_or(0, |preferences| {
preferences.model_request_overages_spend_limit_in_cents
}),
}))
}
#[derive(Debug, Deserialize)]
struct UpdateBillingPreferencesBody {
github_user_id: i32,

View file

@ -1,83 +0,0 @@
use serde::Serialize;
/// A number of cents.
#[derive(
Debug,
PartialEq,
Eq,
PartialOrd,
Ord,
Hash,
Clone,
Copy,
derive_more::Add,
derive_more::AddAssign,
derive_more::Sub,
derive_more::SubAssign,
Serialize,
)]
pub struct Cents(pub u32);
impl Cents {
pub const ZERO: Self = Self(0);
pub const fn new(cents: u32) -> Self {
Self(cents)
}
pub const fn from_dollars(dollars: u32) -> Self {
Self(dollars * 100)
}
pub fn saturating_sub(self, other: Cents) -> Self {
Self(self.0.saturating_sub(other.0))
}
}
#[cfg(test)]
mod tests {
use pretty_assertions::assert_eq;
use super::*;
#[test]
fn test_cents_new() {
assert_eq!(Cents::new(50), Cents(50));
}
#[test]
fn test_cents_from_dollars() {
assert_eq!(Cents::from_dollars(1), Cents(100));
assert_eq!(Cents::from_dollars(5), Cents(500));
}
#[test]
fn test_cents_zero() {
assert_eq!(Cents::ZERO, Cents(0));
}
#[test]
fn test_cents_add() {
assert_eq!(Cents(50) + Cents(30), Cents(80));
}
#[test]
fn test_cents_add_assign() {
let mut cents = Cents(50);
cents += Cents(30);
assert_eq!(cents, Cents(80));
}
#[test]
fn test_cents_saturating_sub() {
assert_eq!(Cents(50).saturating_sub(Cents(30)), Cents(20));
assert_eq!(Cents(30).saturating_sub(Cents(50)), Cents(0));
}
#[test]
fn test_cents_ordering() {
assert!(Cents(50) > Cents(30));
assert!(Cents(30) < Cents(50));
assert_eq!(Cents(50), Cents(50));
}
}

View file

@ -1,6 +1,5 @@
pub mod api;
pub mod auth;
mod cents;
pub mod db;
pub mod env;
pub mod executor;
@ -21,7 +20,6 @@ use axum::{
http::{HeaderMap, StatusCode},
response::IntoResponse,
};
pub use cents::*;
use db::{ChannelId, Database};
use executor::Executor;
use llm::db::LlmDatabase;

View file

@ -1,8 +1,6 @@
pub mod db;
mod token;
use crate::Cents;
pub use token::*;
pub const AGENT_EXTENDED_TRIAL_FEATURE_FLAG: &str = "agent-extended-trial";
@ -12,9 +10,3 @@ pub const BYPASS_ACCOUNT_AGE_CHECK_FEATURE_FLAG: &str = "bypass-account-age-chec
/// The minimum account age an account must have in order to use the LLM service.
pub const MIN_ACCOUNT_AGE_FOR_LLM_USE: chrono::Duration = chrono::Duration::days(30);
/// The default value to use for maximum spend per month if the user did not
/// explicitly set a maximum spend.
///
/// Used to prevent surprise bills.
pub const DEFAULT_MAX_MONTHLY_SPEND: Cents = Cents::from_dollars(10);