Track payment method
This commit is contained in:
@@ -6,6 +6,7 @@ CREATE TABLE IF NOT EXISTS tenant (
|
||||
created_at INTEGER NOT NULL,
|
||||
billing_anchor INTEGER,
|
||||
stripe_customer_id TEXT NOT NULL,
|
||||
stripe_payment_method_id TEXT,
|
||||
renewed_at INTEGER,
|
||||
churned_at INTEGER
|
||||
);
|
||||
|
||||
@@ -233,7 +233,7 @@ impl Billing {
|
||||
/// a relay created/activated *within* the period isn't active before the
|
||||
/// boundary, so it's covered by its own prorated charge instead.
|
||||
async fn reconcile_renewal(&self, tenant: &Tenant, period: &BillingPeriod) -> Result<()> {
|
||||
let relays = query::list_relays(&tenant.pubkey).await?;
|
||||
let relays = query::list_relays_for_tenant(&tenant.pubkey).await?;
|
||||
|
||||
let mut line_items = Vec::new();
|
||||
for relay in relays {
|
||||
@@ -419,7 +419,7 @@ impl Billing {
|
||||
async fn churn_tenant(&self, tenant: &Tenant, now: i64) -> Result<()> {
|
||||
command::set_tenant_churned_at(&tenant.pubkey, Some(now)).await?;
|
||||
|
||||
for relay in query::list_relays(&tenant.pubkey).await? {
|
||||
for relay in query::list_relays_for_tenant(&tenant.pubkey).await? {
|
||||
if relay.status == RELAY_STATUS_ACTIVE {
|
||||
command::mark_relay_delinquent(&relay).await?;
|
||||
}
|
||||
@@ -434,7 +434,7 @@ impl Billing {
|
||||
async fn reactivate_tenant(&self, tenant: &Tenant) -> Result<()> {
|
||||
command::set_tenant_churned_at(&tenant.pubkey, None).await?;
|
||||
|
||||
for relay in query::list_relays(&tenant.pubkey).await? {
|
||||
for relay in query::list_relays_for_tenant(&tenant.pubkey).await? {
|
||||
if relay.status == RELAY_STATUS_DELINQUENT {
|
||||
command::unmark_relay_delinquent(&relay).await?;
|
||||
}
|
||||
|
||||
@@ -46,6 +46,9 @@ pub struct Tenant {
|
||||
pub created_at: i64,
|
||||
pub billing_anchor: Option<i64>,
|
||||
pub stripe_customer_id: String,
|
||||
/// The tenant's saved Stripe payment method, or `None` if they have not set
|
||||
/// up a card yet. Set when the tenant adds a card via the Stripe portal.
|
||||
pub stripe_payment_method_id: Option<String>,
|
||||
/// `period_start` of the most recent period this tenant was renewed for, or
|
||||
/// `None` if never renewed. The per-period renewal idempotency marker.
|
||||
pub renewed_at: Option<i64>,
|
||||
|
||||
@@ -84,7 +84,7 @@ pub async fn list_relays_pending_sync() -> Result<Vec<Relay>> {
|
||||
)
|
||||
}
|
||||
|
||||
pub async fn list_relays(tenant_pubkey: &str) -> Result<Vec<Relay>> {
|
||||
pub async fn list_relays_for_tenant(tenant_pubkey: &str) -> Result<Vec<Relay>> {
|
||||
Ok(sqlx::query_as::<_, Relay>(&select_relay("WHERE tenant_pubkey = ?"))
|
||||
.bind(tenant_pubkey)
|
||||
.fetch_all(pool())
|
||||
|
||||
@@ -22,6 +22,7 @@ pub struct TenantResponse {
|
||||
pub created_at: i64,
|
||||
pub billing_anchor: Option<i64>,
|
||||
pub stripe_customer_id: String,
|
||||
pub stripe_payment_method_id: Option<String>,
|
||||
/// Set when billing has churned the tenant; the UI uses it to warn that the
|
||||
/// account is delinquent until billing is re-activated.
|
||||
pub churned_at: Option<i64>,
|
||||
@@ -37,6 +38,7 @@ impl From<Tenant> for TenantResponse {
|
||||
created_at: t.created_at,
|
||||
billing_anchor: t.billing_anchor,
|
||||
stripe_customer_id: t.stripe_customer_id,
|
||||
stripe_payment_method_id: t.stripe_payment_method_id,
|
||||
churned_at: t.churned_at,
|
||||
}
|
||||
}
|
||||
@@ -142,7 +144,7 @@ pub async fn list_tenant_relays(
|
||||
) -> ApiResult {
|
||||
api.require_admin_or_tenant(&auth, &pubkey)?;
|
||||
|
||||
let relays = query::list_relays(&pubkey)
|
||||
let relays = query::list_relays_for_tenant(&pubkey)
|
||||
.await
|
||||
.map_err(internal)?;
|
||||
ok(relays)
|
||||
|
||||
@@ -98,6 +98,7 @@ export type Tenant = {
|
||||
nwc_is_set: boolean
|
||||
created_at: number
|
||||
stripe_customer_id: string
|
||||
stripe_payment_method_id: string | null
|
||||
nwc_error: string | null
|
||||
stripe_error: string | null
|
||||
churned_at: number | null
|
||||
|
||||
@@ -135,7 +135,7 @@ export const reactivateRelayById = (id: string) => reactivateRelay(id)
|
||||
|
||||
export async function tenantNeedsPaymentSetup(): Promise<boolean> {
|
||||
const tenant = await getTenant(account()!.pubkey)
|
||||
return !tenant.nwc_is_set
|
||||
return !tenant.nwc_is_set && !tenant.stripe_payment_method_id
|
||||
}
|
||||
|
||||
export async function getLatestOpenInvoice(): Promise<Invoice | null> {
|
||||
|
||||
@@ -59,7 +59,7 @@ export default function RelayDetail() {
|
||||
if (!isPaidRelay()) return false
|
||||
const t = tenant()
|
||||
if (!t) return false
|
||||
return !t.nwc_is_set
|
||||
return !t.nwc_is_set && !t.stripe_payment_method_id
|
||||
})
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user