Compare commits

..

2 Commits

Author SHA1 Message Date
Antonio Scandurra
414ea980f9 Subtract FREE_TIER_MONTHLY_SPENDING_LIMIT from reported monthly spend 2024-10-17 12:36:28 +02:00
Antonio Scandurra
7b5f236811 Introduce a new /billing/monthly_spend API 2024-10-17 11:55:41 +02:00
2 changed files with 41 additions and 12 deletions

View File

@@ -19,7 +19,7 @@ use stripe::{
};
use util::ResultExt;
use crate::llm::DEFAULT_MAX_MONTHLY_SPEND;
use crate::llm::{DEFAULT_MAX_MONTHLY_SPEND, FREE_TIER_MONTHLY_SPENDING_LIMIT};
use crate::rpc::{ResultExt as _, Server};
use crate::{
db::{
@@ -50,6 +50,7 @@ pub fn router() -> Router {
"/billing/subscriptions/manage",
post(manage_billing_subscription),
)
.route("/billing/monthly_spend", get(get_monthly_spend))
}
#[derive(Debug, Deserialize)]
@@ -672,6 +673,43 @@ async fn handle_customer_subscription_event(
Ok(())
}
#[derive(Debug, Deserialize)]
struct GetMonthlySpendParams {
github_user_id: i32,
}
#[derive(Debug, Serialize)]
struct GetMonthlySpendResponse {
monthly_spend_in_cents: i32,
}
async fn get_monthly_spend(
Extension(app): Extension<Arc<AppState>>,
Query(params): Query<GetMonthlySpendParams>,
) -> Result<Json<GetMonthlySpendResponse>> {
let user = app
.db
.get_user_by_github_user_id(params.github_user_id)
.await?
.ok_or_else(|| anyhow!("user not found"))?;
let Some(llm_db) = app.llm_db.clone() else {
return Err(Error::http(
StatusCode::NOT_IMPLEMENTED,
"LLM database not available".into(),
));
};
let monthly_spend = llm_db
.get_user_spending_for_month(user.id, Utc::now())
.await?
.saturating_sub(FREE_TIER_MONTHLY_SPENDING_LIMIT);
Ok(Json(GetMonthlySpendResponse {
monthly_spend_in_cents: monthly_spend.0 as i32,
}))
}
impl From<SubscriptionStatus> for StripeSubscriptionStatus {
fn from(value: SubscriptionStatus) -> Self {
match value {

View File

@@ -288,12 +288,6 @@ impl ProjectPicker {
}
}
impl FocusableView for ProjectPicker {
fn focus_handle(&self, cx: &AppContext) -> FocusHandle {
self.picker.focus_handle(cx)
}
}
impl gpui::Render for ProjectPicker {
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
v_flex()
@@ -374,16 +368,13 @@ impl DevServerProjects {
workspace: WeakView<Workspace>,
) -> Self {
let mut this = Self::new(cx, workspace.clone());
let picker = ProjectPicker::new(
this.mode = Mode::ProjectPicker(ProjectPicker::new(
ix,
connection_options.connection_string().into(),
project,
workspace,
cx,
);
let focus_handle = picker.focus_handle(cx);
this.mode = Mode::ProjectPicker(picker);
this.focus_handle = focus_handle;
));
this
}