+ {tierFree.name}
+ {#if $organization?.billingPlan === BillingPlan.FREE && !isNewOrg}
+ Current plan
+ {/if}
+
+
+ {tierFree.description}
+
+
+ {formatCurrency(freePlan?.price ?? 0)}
+
+
+
+
+
+
+
+
+
+
+
+ {tierPro.name}
+ {#if $organization?.billingPlan === BillingPlan.PRO && !isNewOrg}
+ Current plan
+ {/if}
+
+
+ {tierPro.description}
+
+
+ {formatCurrency(proPlan?.price ?? 0)} per member/month + usage
+
+
+
+
+
+
+
+
+
+
+ {tierScale.name}
+ {#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg}
+ Current plan
+ {/if}
+
+
+ {tierScale.description}
+
+
+ {formatCurrency(scalePlan?.price ?? 0)} per month + usage
+
+
+
+
+
+
+{/if}
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index 5e54db955..ce7adccf7 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -150,7 +150,7 @@ export const tierPro: TierData = {
};
export const tierScale: TierData = {
name: 'Scale',
- description: 'For scaling teams that need dedicated support.'
+ description: 'For scaling teams and agencies that need dedicated support.'
};
export const showUsageRatesModal = writable(false);
@@ -422,14 +422,14 @@ export const upgradeURL = derived(
export const hideBillingHeaderRoutes = ['/console/create-organization', '/console/account'];
-export function calculateExcess(usage: OrganizationUsage, plan: Plan, org: Organization) {
+export function calculateExcess(usage: OrganizationUsage, plan: Plan, members: number) {
const totBandwidth = usage?.bandwidth?.length > 0 ? last(usage.bandwidth).value : 0;
return {
bandwidth: calculateResourceSurplus(totBandwidth, plan.bandwidth),
storage: calculateResourceSurplus(usage?.storageTotal, plan.storage, 'GB'),
users: calculateResourceSurplus(usage?.usersTotal, plan.users),
executions: calculateResourceSurplus(usage?.executionsTotal, plan.executions, 'GB'),
- members: calculateResourceSurplus(org.total, plan.members)
+ members: calculateResourceSurplus(members, plan.members)
};
}
diff --git a/src/lib/stores/campaigns.ts b/src/lib/stores/campaigns.ts
index 3f7866b9e..315a4230f 100644
--- a/src/lib/stores/campaigns.ts
+++ b/src/lib/stores/campaigns.ts
@@ -1,11 +1,14 @@
//campaign welcome and startup
+import { BillingPlan } from '$lib/constants';
+
export type CampaignData = {
title: string;
description: string;
template: 'card' | 'review';
data?: Record;
onlyNewOrgs?: boolean;
+ plan?: BillingPlan;
footer?: boolean;
};
@@ -22,7 +25,7 @@ campaigns
template: 'card',
title: 'Welcome to the Startups program!',
description:
- "We're excited to have you on board. Add the coupon code to your Appwrite Pro account to join."
+ "We're excited to have you on board. Add the coupon code to your Appwrite Scale account to join."
})
.set('RenderATL2024', {
template: 'card',
@@ -52,10 +55,11 @@ campaigns
template: 'review',
title: 'Welcome to the Startups program',
description:
- "We're excited to have you on board. Add your credit code to your Appwrite Pro account to join.",
+ "We're excited to have you on board. Add your credit code to your Appwrite Scale account to join.",
onlyNewOrgs: true,
+ plan: BillingPlan.SCALE,
data: {
- cta: 'Get everything out of Cloud with Pro',
+ cta: 'Get everything out of Cloud with Scale',
claimed: 'Your credits will be valid for 12 months.',
unclaimed: 'Apply your code to join the Startups program.',
reviews: [
diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts
index 2beb13b03..f0f363d56 100644
--- a/src/lib/stores/organization.ts
+++ b/src/lib/stores/organization.ts
@@ -19,7 +19,7 @@ export type Organization = Models.Team> & {
billingAddressId?: string;
amount: number;
billingTaxId?: string;
- billingPlanDowngrade?: string;
+ billingPlanDowngrade?: Tier;
};
export type OrganizationList = {
diff --git a/src/routes/console/apply-credit/+page.svelte b/src/routes/console/apply-credit/+page.svelte
index c9f0db557..231c8820f 100644
--- a/src/routes/console/apply-credit/+page.svelte
+++ b/src/routes/console/apply-credit/+page.svelte
@@ -70,6 +70,7 @@
let coupon: string;
let couponData = data?.couponData;
let campaign = campaigns.get(data?.couponData?.campaign ?? data?.campaign);
+ let billingPlan = BillingPlan.PRO;
onMount(async () => {
await loadPaymentMethods();
@@ -80,6 +81,9 @@
selectedOrgId = $page.url.searchParams.get('org');
canSelectOrg = false;
}
+ if (campaign?.plan) {
+ billingPlan = campaign.plan;
+ }
});
async function loadPaymentMethods() {
@@ -101,15 +105,15 @@
org = await sdk.forConsole.billing.createOrganization(
newOrgId,
name,
- BillingPlan.PRO,
+ billingPlan,
paymentMethodId
);
}
// Upgrade existing org
- else if (selectedOrg?.billingPlan !== BillingPlan.PRO) {
+ else if (selectedOrg?.billingPlan === BillingPlan.FREE) {
org = await sdk.forConsole.billing.updatePlan(
selectedOrg.$id,
- BillingPlan.PRO,
+ billingPlan,
paymentMethodId,
null
);
@@ -270,7 +274,7 @@
{/if}
- {#if selectedOrg?.billingPlan === BillingPlan.PRO}
+ {#if selectedOrg?.billingPlan !== BillingPlan.FREE}
(org as Organization)?.billingPlan === BillingPlan.FREE
);
const emailRegex = /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,63}$/i;
@@ -175,9 +174,7 @@
}
}
- $: freePlan = $plansInfo.get(BillingPlan.FREE);
- $: proPlan = $plansInfo.get(BillingPlan.PRO);
- $: if (billingPlan === BillingPlan.PRO) {
+ $: if (billingPlan !== BillingPlan.FREE) {
loadPaymentMethods();
}
@@ -205,53 +202,9 @@
For more details on our plans, visit our
.
-
-
-
-
-
-
- {tierFree.name}
-
-
{tierFree.description}
-
- {formatCurrency(freePlan?.price ?? 0)}
-
-
-
-
-
-
-
-
-
-
-
- {tierPro.name}
-
-
- {tierPro.description}
-
-
- {formatCurrency(proPlan?.price ?? 0)} per member/month + usage
-
-
-
-
-
-
- {#if billingPlan === BillingPlan.PRO}
-
+
+ {#if billingPlan !== BillingPlan.FREE}
+
- Your organization will change to a {tierToPlan(BillingPlan.FREE).name} plan once your current
- billing cycle ends and your invoice is paid on {toLocaleDate(
+ Your organization will change to a {tierToPlan($organization?.billingPlanDowngrade)
+ .name} plan once your current billing cycle ends and your invoice is paid on {toLocaleDate(
$organization.billingNextInvoiceDate
)}.
diff --git a/src/routes/console/organization-[organization]/billing/planSummary.svelte b/src/routes/console/organization-[organization]/billing/planSummary.svelte
index 81edb295e..04d1aa258 100644
--- a/src/routes/console/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/console/organization-[organization]/billing/planSummary.svelte
@@ -58,7 +58,7 @@
{isTrial ? formatCurrency(0) : formatCurrency(currentPlan?.price)}
- {#if $organization?.billingPlan !== BillingPlan.FREE && extraUsage}
+ {#if $organization?.billingPlan !== BillingPlan.FREE && extraUsage > 0}
Add-ons $organization.billingPlan;
$: isDowngrade = billingPlan < $organization.billingPlan;
- $: freePlan = $plansInfo.get(BillingPlan.FREE);
- $: proPlan = $plansInfo.get(BillingPlan.PRO);
- $: if (billingPlan === BillingPlan.PRO) {
+ $: if (billingPlan !== BillingPlan.FREE) {
loadPaymentMethods();
}
$: isButtonDisabled = $organization.billingPlan === billingPlan;
@@ -261,72 +264,37 @@
For more details on our plans, visit our
.
- {#if anyOrgFree && billingPlan === BillingPlan.PRO}
-
- You are limited to one {tierToPlan(BillingPlan.FREE).name} organization per account.
- Consider upgrading or deleting .
-
- {/if}
-
-
-
-
-
-
- {tierFree.name}
- {#if $organization.billingPlan === BillingPlan.FREE}
- Current plan
- {/if}
-
-
{tierFree.description}
-
- {formatCurrency(freePlan?.price ?? 0)}
-
-
-
-
-
+
-
-
-
-
-
- {tierPro.name}
- {#if $organization.billingPlan === BillingPlan.PRO}
- Current plan
- {/if}
-
-
- {tierPro.description}
-
-
- {formatCurrency(proPlan?.price ?? 0)} per member/month + usage
-
-
-
-
-
-
{#if isDowngrade}
-
+ {#if billingPlan === BillingPlan.FREE}
+
+ {:else if billingPlan === BillingPlan.PRO && $organization.billingPlan === BillingPlan.SCALE}
+ {@const extraMembers = collaborators?.length ?? 0}
+
+
+ Your monthly payments will be adjusted for the Pro plan
+
+ After switching plans,
+ you will be charged {formatCurrency(
+ extraMembers *
+ ($plansInfo?.get(billingPlan)?.addons?.member?.price ?? 0)
+ )} monthly for {extraMembers} team members. This will be reflected in
+ your next invoice.
+
+ {/if}
{/if}
- {#if billingPlan === BillingPlan.PRO && $organization.billingPlan !== BillingPlan.PRO}
+
+ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan === BillingPlan.FREE}
{/if}
{/if}
- {#if !isUpgrade && billingPlan === BillingPlan.FREE && $organization.billingPlan !== BillingPlan.FREE}
+ {#if isDowngrade}
- {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== BillingPlan.PRO}
+ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan}
+ bind:billingBudget
+ {isDowngrade} />
{:else}
{/if}
diff --git a/src/routes/console/organization-[organization]/change-plan/+page.ts b/src/routes/console/organization-[organization]/change-plan/+page.ts
index cde580678..b10332405 100644
--- a/src/routes/console/organization-[organization]/change-plan/+page.ts
+++ b/src/routes/console/organization-[organization]/change-plan/+page.ts
@@ -2,8 +2,8 @@ import { Dependencies } from '$lib/constants';
export const load = async ({ depends, parent }) => {
const { members } = await parent();
- depends(Dependencies.ORGANIZATION);
+ depends(Dependencies.ORGANIZATION);
return {
members
};
diff --git a/src/routes/console/organization-[organization]/createMember.svelte b/src/routes/console/organization-[organization]/createMember.svelte
index a0c4ff0dc..c3195a1f2 100644
--- a/src/routes/console/organization-[organization]/createMember.svelte
+++ b/src/routes/console/organization-[organization]/createMember.svelte
@@ -59,14 +59,12 @@
{#if isCloud}
-
- {#if $organization?.billingPlan === BillingPlan.SCALE}
- You can add unlimited organization members on the {plan.name} plan at no cost.
- {:else if $organization?.billingPlan === BillingPlan.PRO}
+ {#if $organization?.billingPlan === BillingPlan.PRO}
+
You can add unlimited organization members on the {plan.name} plan for
{formatCurrency(plan.addons.member.price)} each per billing period.
- {/if}
-
+
+ {/if}
{/if}