mirror of https://github.com/kortix-ai/suna.git
billing stuff
This commit is contained in:
parent
4bcbea3464
commit
24d95d278c
|
@ -1,12 +1,11 @@
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Dict, Optional, Tuple
|
from typing import Dict, Optional, Tuple
|
||||||
from services.supabase import DBConnection
|
|
||||||
|
|
||||||
# Define subscription tiers and their monthly hour limits
|
# Define subscription tiers and their monthly limits (in minutes)
|
||||||
SUBSCRIPTION_TIERS = {
|
SUBSCRIPTION_TIERS = {
|
||||||
'price_1RDQbOG6l1KZGqIrgrYzMbnL': {'name': 'free', 'hours': 100},
|
'price_1RGJ9GG6l1KZGqIroxSqgphC': {'name': 'free', 'minutes': 10},
|
||||||
'price_1RC2PYG6l1KZGqIrpbzFB9Lp': {'name': 'base', 'hours': 100},
|
'price_1RGJ9LG6l1KZGqIrd9pwzeNW': {'name': 'base', 'minutes': 6000}, # 100 hours = 6000 minutes
|
||||||
'price_1RDQWqG6l1KZGqIrChli4Ys4': {'name': 'extra', 'hours': 100}
|
'price_1RGJ9JG6l1KZGqIrVUU4ZRv6': {'name': 'extra', 'minutes': 6000} # 100 hours = 6000 minutes
|
||||||
}
|
}
|
||||||
|
|
||||||
async def get_account_subscription(client, account_id: str) -> Optional[Dict]:
|
async def get_account_subscription(client, account_id: str) -> Optional[Dict]:
|
||||||
|
@ -24,7 +23,7 @@ async def get_account_subscription(client, account_id: str) -> Optional[Dict]:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
async def calculate_monthly_usage(client, account_id: str) -> float:
|
async def calculate_monthly_usage(client, account_id: str) -> float:
|
||||||
"""Calculate total agent run hours for the current month for an account."""
|
"""Calculate total agent run minutes for the current month for an account."""
|
||||||
# Get start of current month in UTC
|
# Get start of current month in UTC
|
||||||
now = datetime.now(timezone.utc)
|
now = datetime.now(timezone.utc)
|
||||||
start_of_month = datetime(now.year, now.month, 1, tzinfo=timezone.utc)
|
start_of_month = datetime(now.year, now.month, 1, tzinfo=timezone.utc)
|
||||||
|
@ -50,7 +49,7 @@ async def calculate_monthly_usage(client, account_id: str) -> float:
|
||||||
if not runs_result.data:
|
if not runs_result.data:
|
||||||
return 0.0
|
return 0.0
|
||||||
|
|
||||||
# Calculate total hours
|
# Calculate total minutes
|
||||||
total_seconds = 0
|
total_seconds = 0
|
||||||
now_ts = now.timestamp()
|
now_ts = now.timestamp()
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ async def calculate_monthly_usage(client, account_id: str) -> float:
|
||||||
|
|
||||||
total_seconds += (end_time - start_time)
|
total_seconds += (end_time - start_time)
|
||||||
|
|
||||||
return total_seconds / 3600 # Convert to hours
|
return total_seconds / 60 # Convert to minutes
|
||||||
|
|
||||||
async def check_billing_status(client, account_id: str) -> Tuple[bool, str, Optional[Dict]]:
|
async def check_billing_status(client, account_id: str) -> Tuple[bool, str, Optional[Dict]]:
|
||||||
"""
|
"""
|
||||||
|
@ -79,7 +78,7 @@ async def check_billing_status(client, account_id: str) -> Tuple[bool, str, Opti
|
||||||
# If no subscription, they can use free tier
|
# If no subscription, they can use free tier
|
||||||
if not subscription:
|
if not subscription:
|
||||||
subscription = {
|
subscription = {
|
||||||
'price_id': 'price_1RDQbOG6l1KZGqIrgrYzMbnL', # Free tier
|
'price_id': 'price_1RGJ9GG6l1KZGqIroxSqgphC', # Free tier
|
||||||
'plan_name': 'Free'
|
'plan_name': 'Free'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,8 +91,8 @@ async def check_billing_status(client, account_id: str) -> Tuple[bool, str, Opti
|
||||||
current_usage = await calculate_monthly_usage(client, account_id)
|
current_usage = await calculate_monthly_usage(client, account_id)
|
||||||
|
|
||||||
# Check if within limits
|
# Check if within limits
|
||||||
if current_usage >= tier_info['hours']:
|
if current_usage >= tier_info['minutes']:
|
||||||
return False, f"Monthly limit of {tier_info['hours']} hours reached. Please upgrade your plan or wait until next month.", subscription
|
return False, f"Monthly limit of {tier_info['minutes']} minutes reached. Please upgrade your plan or wait until next month.", subscription
|
||||||
|
|
||||||
return True, "OK", subscription
|
return True, "OK", subscription
|
||||||
|
|
||||||
|
|
|
@ -9,9 +9,9 @@ import { SubmitButton } from "@/components/ui/submit-button";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { siteConfig } from "@/lib/home";
|
import { siteConfig } from "@/lib/home";
|
||||||
export const SUBSCRIPTION_PLANS = {
|
export const SUBSCRIPTION_PLANS = {
|
||||||
FREE: 'price_1RDQbOG6l1KZGqIrgrYzMbnL',
|
FREE: 'price_1RGJ9GG6l1KZGqIroxSqgphC',
|
||||||
BASIC: 'price_1RC2PYG6l1KZGqIrpbzFB9Lp',
|
BASIC: 'price_1RGJ9LG6l1KZGqIrd9pwzeNW',
|
||||||
PRO: 'price_1RDQWqG6l1KZGqIrChli4Ys4'
|
PRO: 'price_1RGJ9JG6l1KZGqIrVUU4ZRv6'
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
interface PlanComparisonProps {
|
interface PlanComparisonProps {
|
||||||
|
@ -171,6 +171,16 @@ export function PlanComparison({
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{(tier as any).showContactSales && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
className="w-full h-10 rounded-full font-medium transition-colors mt-4"
|
||||||
|
onClick={() => window.open('mailto:support@kortix.ai?subject=Enterprise Plan Inquiry', '_blank')}
|
||||||
|
>
|
||||||
|
Need more? Contact Sales
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -366,6 +366,15 @@ export function PricingSection() {
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
{(tier as any).showContactSales && (
|
||||||
|
<button
|
||||||
|
className="h-10 w-full flex items-center justify-center text-sm font-normal tracking-wide rounded-full px-4 cursor-pointer transition-all ease-out active:scale-95 bg-transparent border border-secondary/20 text-secondary shadow-[0px_1px_2px_0px_rgba(255,255,255,0.05)_inset] mt-6"
|
||||||
|
onClick={() => window.open('mailto:support@kortix.ai?subject=Enterprise Plan Inquiry', '_blank')}
|
||||||
|
>
|
||||||
|
Need more? Contact Sales
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
|
@ -111,7 +111,7 @@ export const siteConfig = {
|
||||||
name: "Enterprise",
|
name: "Enterprise",
|
||||||
price: "$199",
|
price: "$199",
|
||||||
description: "For organizations with complex needs",
|
description: "For organizations with complex needs",
|
||||||
buttonText: "Contact Sales",
|
buttonText: "Hire Suna",
|
||||||
buttonColor: "bg-secondary text-white",
|
buttonColor: "bg-secondary text-white",
|
||||||
isPopular: false,
|
isPopular: false,
|
||||||
hours: "40 hours",
|
hours: "40 hours",
|
||||||
|
@ -123,6 +123,7 @@ export const siteConfig = {
|
||||||
"Service level agreement",
|
"Service level agreement",
|
||||||
"Custom AI model training",
|
"Custom AI model training",
|
||||||
],
|
],
|
||||||
|
showContactSales: true,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
companyShowcase: {
|
companyShowcase: {
|
||||||
|
|
Loading…
Reference in New Issue