Add overdue invoices check (#31290)
- Rename current_user_account_too_young to account_too_young for consistency - Add has_overdue_invoices field to track billing status - Block edit predictions when user has overdue invoices - Add overdue invoice warning to inline completion menu Release Notes: - N/A --------- Co-authored-by: Marshall Bowers <git@maxdeviant.com>
This commit is contained in:
parent
cb112a4012
commit
ca72efe701
7 changed files with 65 additions and 7 deletions
|
@ -1973,7 +1973,7 @@ impl AgentPanel {
|
|||
return None;
|
||||
}
|
||||
|
||||
if self.user_store.read(cx).current_user_account_too_young() {
|
||||
if self.user_store.read(cx).account_too_young() {
|
||||
Some(self.render_young_account_upsell(cx).into_any_element())
|
||||
} else {
|
||||
Some(self.render_trial_upsell(cx).into_any_element())
|
||||
|
|
|
@ -109,6 +109,7 @@ pub struct UserStore {
|
|||
edit_predictions_usage_limit: Option<proto::UsageLimit>,
|
||||
is_usage_based_billing_enabled: Option<bool>,
|
||||
account_too_young: Option<bool>,
|
||||
has_overdue_invoices: Option<bool>,
|
||||
current_user: watch::Receiver<Option<Arc<User>>>,
|
||||
accepted_tos_at: Option<Option<DateTime<Utc>>>,
|
||||
contacts: Vec<Arc<Contact>>,
|
||||
|
@ -176,6 +177,7 @@ impl UserStore {
|
|||
edit_predictions_usage_limit: None,
|
||||
is_usage_based_billing_enabled: None,
|
||||
account_too_young: None,
|
||||
has_overdue_invoices: None,
|
||||
accepted_tos_at: None,
|
||||
contacts: Default::default(),
|
||||
incoming_contact_requests: Default::default(),
|
||||
|
@ -350,6 +352,7 @@ impl UserStore {
|
|||
.and_then(|trial_started_at| DateTime::from_timestamp(trial_started_at as i64, 0));
|
||||
this.is_usage_based_billing_enabled = message.payload.is_usage_based_billing_enabled;
|
||||
this.account_too_young = message.payload.account_too_young;
|
||||
this.has_overdue_invoices = message.payload.has_overdue_invoices;
|
||||
|
||||
if let Some(usage) = message.payload.usage {
|
||||
this.model_request_usage_amount = Some(usage.model_requests_usage_amount);
|
||||
|
@ -755,11 +758,16 @@ impl UserStore {
|
|||
self.current_user.clone()
|
||||
}
|
||||
|
||||
/// Check if the current user's account is too new to use the service
|
||||
pub fn current_user_account_too_young(&self) -> bool {
|
||||
/// Returns whether the user's account is too new to use the service.
|
||||
pub fn account_too_young(&self) -> bool {
|
||||
self.account_too_young.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns whether the current user has overdue invoices and usage should be blocked.
|
||||
pub fn has_overdue_invoices(&self) -> bool {
|
||||
self.has_overdue_invoices.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn current_user_has_accepted_terms(&self) -> Option<bool> {
|
||||
self.accepted_tos_at
|
||||
.map(|accepted_tos_at| accepted_tos_at.is_some())
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::db::billing_subscription::SubscriptionKind;
|
||||
use crate::db::{billing_subscription, user};
|
||||
use crate::db::{billing_customer, billing_subscription, user};
|
||||
use crate::llm::AGENT_EXTENDED_TRIAL_FEATURE_FLAG;
|
||||
use crate::{Config, db::billing_preference};
|
||||
use anyhow::{Context as _, Result};
|
||||
|
@ -32,6 +32,8 @@ pub struct LlmTokenClaims {
|
|||
pub enable_model_request_overages: bool,
|
||||
pub model_request_overages_spend_limit_in_cents: u32,
|
||||
pub can_use_web_search_tool: bool,
|
||||
#[serde(default)]
|
||||
pub has_overdue_invoices: bool,
|
||||
}
|
||||
|
||||
const LLM_TOKEN_LIFETIME: Duration = Duration::from_secs(60 * 60);
|
||||
|
@ -40,6 +42,7 @@ impl LlmTokenClaims {
|
|||
pub fn create(
|
||||
user: &user::Model,
|
||||
is_staff: bool,
|
||||
billing_customer: billing_customer::Model,
|
||||
billing_preferences: Option<billing_preference::Model>,
|
||||
feature_flags: &Vec<String>,
|
||||
subscription: billing_subscription::Model,
|
||||
|
@ -99,6 +102,7 @@ impl LlmTokenClaims {
|
|||
.map_or(0, |preferences| {
|
||||
preferences.model_request_overages_spend_limit_in_cents as u32
|
||||
}),
|
||||
has_overdue_invoices: billing_customer.has_overdue_invoices,
|
||||
};
|
||||
|
||||
Ok(jsonwebtoken::encode(
|
||||
|
|
|
@ -2748,6 +2748,7 @@ async fn make_update_user_plan_message(
|
|||
Ok(proto::UpdateUserPlan {
|
||||
plan: plan.into(),
|
||||
trial_started_at: billing_customer
|
||||
.as_ref()
|
||||
.and_then(|billing_customer| billing_customer.trial_started_at)
|
||||
.map(|trial_started_at| trial_started_at.and_utc().timestamp() as u64),
|
||||
is_usage_based_billing_enabled: if is_staff {
|
||||
|
@ -2762,6 +2763,8 @@ async fn make_update_user_plan_message(
|
|||
}
|
||||
}),
|
||||
account_too_young: Some(account_too_young),
|
||||
has_overdue_invoices: billing_customer
|
||||
.map(|billing_customer| billing_customer.has_overdue_invoices),
|
||||
usage: usage.map(|usage| {
|
||||
let plan = match plan {
|
||||
proto::Plan::Free => zed_llm_client::Plan::ZedFree,
|
||||
|
@ -4077,6 +4080,7 @@ async fn get_llm_api_token(
|
|||
let token = LlmTokenClaims::create(
|
||||
&user,
|
||||
session.is_staff(),
|
||||
billing_customer,
|
||||
billing_preferences,
|
||||
&flags,
|
||||
billing_subscription,
|
||||
|
|
|
@ -745,7 +745,7 @@ impl InlineCompletionButton {
|
|||
})
|
||||
})
|
||||
.separator();
|
||||
} else if self.user_store.read(cx).current_user_account_too_young() {
|
||||
} else if self.user_store.read(cx).account_too_young() {
|
||||
menu = menu
|
||||
.custom_entry(
|
||||
|_window, _cx| {
|
||||
|
@ -785,6 +785,46 @@ impl InlineCompletionButton {
|
|||
},
|
||||
)
|
||||
.separator();
|
||||
} else if self.user_store.read(cx).has_overdue_invoices() {
|
||||
menu = menu
|
||||
.custom_entry(
|
||||
|_window, _cx| {
|
||||
h_flex()
|
||||
.gap_1()
|
||||
.child(
|
||||
Icon::new(IconName::Warning)
|
||||
.size(IconSize::Small)
|
||||
.color(Color::Warning),
|
||||
)
|
||||
.child(
|
||||
Label::new("You have an outstanding invoice")
|
||||
.size(LabelSize::Small)
|
||||
.color(Color::Warning),
|
||||
)
|
||||
.into_any_element()
|
||||
},
|
||||
|window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(OpenZedUrl {
|
||||
url: zed_urls::account_url(cx),
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
},
|
||||
)
|
||||
.entry(
|
||||
"Check your payment status or contact us at billing-support@zed.dev to continue using this feature.",
|
||||
None,
|
||||
|window, cx| {
|
||||
window.dispatch_action(
|
||||
Box::new(OpenZedUrl {
|
||||
url: zed_urls::account_url(cx),
|
||||
}),
|
||||
cx,
|
||||
);
|
||||
},
|
||||
)
|
||||
.separator();
|
||||
}
|
||||
|
||||
self.build_language_settings_menu(menu, window, cx).when(
|
||||
|
|
|
@ -28,6 +28,7 @@ message UpdateUserPlan {
|
|||
optional SubscriptionUsage usage = 4;
|
||||
optional SubscriptionPeriod subscription_period = 5;
|
||||
optional bool account_too_young = 6;
|
||||
optional bool has_overdue_invoices = 7;
|
||||
}
|
||||
|
||||
message SubscriptionPeriod {
|
||||
|
|
|
@ -1578,8 +1578,9 @@ impl inline_completion::EditPredictionProvider for ZetaInlineCompletionProvider
|
|||
.zeta
|
||||
.read(cx)
|
||||
.user_store
|
||||
.read(cx)
|
||||
.current_user_account_too_young()
|
||||
.read_with(cx, |user_store, _| {
|
||||
user_store.account_too_young() || user_store.has_overdue_invoices()
|
||||
})
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue