diff --git a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.constants.ts b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.constants.ts index 5917d61ef6d..8bc29fce204 100644 --- a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.constants.ts +++ b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.constants.ts @@ -11,6 +11,7 @@ export const chargeableProducts: ChargeableProduct[] = [ costPerUnit: 0.125, unitQuantity: 1000000000, // 1GB pricingModel: 'max', + freeQuota: 8000000000, // 8GB }, { title: 'Database Egress', @@ -18,6 +19,7 @@ export const chargeableProducts: ChargeableProduct[] = [ costPerUnit: 0.09, unitQuantity: 1000000000, // 1GB pricingModel: 'sum', + freeQuota: 50000000000, // 50GB }, ], }, @@ -31,6 +33,7 @@ export const chargeableProducts: ChargeableProduct[] = [ costPerUnit: 0.021, unitQuantity: 1000000000, // 1GB pricingModel: 'max', + freeQuota: 100000000000, // 100GB }, { title: 'Storage Egress', @@ -38,6 +41,7 @@ export const chargeableProducts: ChargeableProduct[] = [ costPerUnit: 0.09, unitQuantity: 1000000000, // 1GB pricingModel: 'sum', + freeQuota: 200000000000, // 200GB }, ], }, diff --git a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.types.ts b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.types.ts index 64f953da2c3..5f5c5159ea4 100644 --- a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.types.ts +++ b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.types.ts @@ -10,6 +10,7 @@ export interface ProductFeature { costPerUnit: number unitQuantity: number pricingModel: PricingModel + freeQuota?: number } export type PaygStats = { [key: string]: { sum: number; max: number } } diff --git a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.utils.ts b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.utils.ts index ff60a4905ed..3f12047e3b7 100644 --- a/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.utils.ts +++ b/studio/components/interfaces/Billing/PAYGUsage/PAYGUsage.utils.ts @@ -12,7 +12,24 @@ import { ChargeableProduct, PaygStats, ProductFeature } from './PAYGUsage.types' * @returns number */ export const deriveFeatureCost = (paygStats: PaygStats | undefined, feature: ProductFeature) => { - const maximumValueOfTheMonth = paygStats?.[feature.attribute]?.[feature.pricingModel] ?? 0 + let rawUsage = paygStats?.[feature.attribute]?.[feature.pricingModel] + + /** + * Some features have a free quota + * + * Check there is included free quota, + * and remove free quota amount from the raw usage derived from paygStats + * + * if the number is negative, then Math.max should return 0 + * + * todo: move this logic to backend @mildtomato + */ + if (rawUsage && feature.freeQuota) { + rawUsage = Math.max(0, rawUsage - feature.freeQuota) + } + + const maximumValueOfTheMonth = rawUsage ?? 0 + return (maximumValueOfTheMonth / feature.unitQuantity) * feature.costPerUnit } diff --git a/studio/components/interfaces/Billing/Subscription/CostBreakdownRow.tsx b/studio/components/interfaces/Billing/Subscription/CostBreakdownRow.tsx index c86b3f5d147..fd679cfcb03 100644 --- a/studio/components/interfaces/Billing/Subscription/CostBreakdownRow.tsx +++ b/studio/components/interfaces/Billing/Subscription/CostBreakdownRow.tsx @@ -1,27 +1,33 @@ import { FC } from 'react' -import { Typography } from '@supabase/ui' +import { Badge, Typography } from '@supabase/ui' interface Props { item: string amount: number | string unitPrice: number | string price: number | string + freeQuota?: number } -const CostBreakdownRow: FC = ({ item, amount, unitPrice, price }) => { +const CostBreakdownRow: FC = ({ item, amount, unitPrice, price, freeQuota }) => { return ( -
-
- {item} +
+
+ {item} + {freeQuota && ( + + {`${freeQuota / 1000000000}GB included`} + + )}
-
- {amount} +
+ {amount}
-
- ${unitPrice} +
+ ${unitPrice}
-
- ${price} +
+ ${price}
) diff --git a/studio/components/interfaces/Billing/Subscription/Subscription.tsx b/studio/components/interfaces/Billing/Subscription/Subscription.tsx index 437b6bc4381..dfc7de081a0 100644 --- a/studio/components/interfaces/Billing/Subscription/Subscription.tsx +++ b/studio/components/interfaces/Billing/Subscription/Subscription.tsx @@ -12,7 +12,7 @@ import CostBreakdownRow from './CostBreakdownRow' import { StripeSubscription } from './Subscription.types' import { deriveFeatureCost, deriveProductCost } from '../PAYGUsage/PAYGUsage.utils' import { chargeableProducts } from '../PAYGUsage/PAYGUsage.constants' -import { PaygStats } from '../PAYGUsage/PAYGUsage.types' +import { PaygStats, ProductFeature } from '../PAYGUsage/PAYGUsage.types' interface Props { project: any @@ -56,14 +56,14 @@ const Subscription: FC = ({ return ( -
+
-
+

{showProjectName ? project.name : 'Current subscription'}

-

{subscription?.tier.name ?? '-'}

+

{subscription?.tier.name ?? '-'}

{!isOrgOwner && ( -

+

Only the organization owner can amend subscriptions

)} @@ -89,7 +89,7 @@ const Subscription: FC = ({
)}