From c67fea49824e3c541c46aeaf578a4b81b348f84e Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 28 Aug 2024 02:57:28 +0000
Subject: [PATCH 01/39] update create
---
src/lib/sdk/billing.ts | 8 ++-
.../console/create-organization/+page.svelte | 51 ++++++++-----------
2 files changed, 27 insertions(+), 32 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index f0fd8ec089..ebe2a55571 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -307,7 +307,9 @@ export class Billing {
name: string,
billingPlan: string,
paymentMethodId: string,
- billingAddressId: string = undefined
+ billingAddressId: string = undefined,
+ couponId: string = undefined,
+ invites: Array = []
): Promise {
const path = `/organizations`;
const params = {
@@ -315,7 +317,9 @@ export class Billing {
name,
billingPlan,
paymentMethodId,
- billingAddressId
+ billingAddressId,
+ couponId,
+ invites
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index e7ac26659d..1b9dd8b458 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -103,23 +103,14 @@
null
);
} else {
- // Create free organization if coming from onboarding
- if (previousPage.includes('/console/onboarding') && !anyOrgFree) {
- await sdk.forConsole.billing.createOrganization(
- ID.unique(),
- 'Personal Projects',
- BillingPlan.FREE,
- null,
- null
- );
- }
-
org = await sdk.forConsole.billing.createOrganization(
ID.unique(),
name,
billingPlan,
paymentMethodId,
- null
+ null,
+ couponData?.code,
+ collaborators
);
//Add budget
@@ -127,25 +118,25 @@
await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]);
}
- //Add coupon
- if (couponData?.code) {
- await sdk.forConsole.billing.addCredit(org.$id, couponData.code);
- trackEvent(Submit.CreditRedeem);
- }
+ // //Add coupon
+ // if (couponData?.code) {
+ // await sdk.forConsole.billing.addCredit(org.$id, couponData.code);
+ // trackEvent(Submit.CreditRedeem);
+ // }
- //Add collaborators
- if (collaborators?.length) {
- collaborators.forEach(async (collaborator) => {
- await sdk.forConsole.teams.createMembership(
- org.$id,
- ['owner'],
- collaborator,
- undefined,
- undefined,
- `${$page.url.origin}/console/organization-${org.$id}`
- );
- });
- }
+ // //Add collaborators
+ // if (collaborators?.length) {
+ // collaborators.forEach(async (collaborator) => {
+ // await sdk.forConsole.teams.createMembership(
+ // org.$id,
+ // ['owner'],
+ // collaborator,
+ // undefined,
+ // undefined,
+ // `${$page.url.origin}/console/organization-${org.$id}`
+ // );
+ // });
+ // }
// Add tax ID
if (taxId) {
From 708517a0d075ee90e7706770e388a455b5635ae5 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 28 Aug 2024 11:08:18 +0545
Subject: [PATCH 02/39] authorize payment
---
.../commandCenter/searchers/organizations.ts | 2 +-
src/lib/sdk/billing.ts | 4 ++--
src/lib/stores/organization.ts | 9 ++++++++
src/routes/+layout.ts | 2 +-
.../console/account/organizations/+page.ts | 2 +-
.../console/create-organization/+page.svelte | 21 ++++++++++++++++---
6 files changed, 32 insertions(+), 8 deletions(-)
diff --git a/src/lib/commandCenter/searchers/organizations.ts b/src/lib/commandCenter/searchers/organizations.ts
index df72d77b26..e5e8d76940 100644
--- a/src/lib/commandCenter/searchers/organizations.ts
+++ b/src/lib/commandCenter/searchers/organizations.ts
@@ -3,7 +3,7 @@ import { sdk } from '$lib/stores/sdk';
import type { Searcher } from '../commands';
export const orgSearcher = (async (query: string) => {
- const { teams } = await sdk.forConsole.teams.list();
+ const { teams } = await sdk.forConsole.billing.listOrganization();
return teams
.filter((organization) => organization.name.toLowerCase().includes(query.toLowerCase()))
.map((organization) => {
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index ebe2a55571..ea278c5bac 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -1,5 +1,5 @@
import type { Client, Models } from '@appwrite.io/console';
-import type { Organization, OrganizationList } from '../stores/organization';
+import type { CreateOrgAuth, Organization, OrganizationList } from '../stores/organization';
import type { PaymentMethod } from '@stripe/stripe-js';
import type { Tier } from '$lib/stores/billing';
@@ -310,7 +310,7 @@ export class Billing {
billingAddressId: string = undefined,
couponId: string = undefined,
invites: Array = []
- ): Promise {
+ ): Promise {
const path = `/organizations`;
const params = {
organizationId,
diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts
index 2beb13b03c..d41cc3f54a 100644
--- a/src/lib/stores/organization.ts
+++ b/src/lib/stores/organization.ts
@@ -3,6 +3,15 @@ import { derived, writable } from 'svelte/store';
import type { Models } from '@appwrite.io/console';
import type { Tier } from './billing';
+export type CreateOrgAuth = {
+ status: number;
+ message: string;
+ teamId: string;
+ invoiceId: string;
+ clientSecret: string;
+ type: string;
+};
+
export type Organization = Models.Team> & {
billingBudget: number;
billingPlan: Tier;
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 85ad4e83d9..5f0472229f 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -22,7 +22,7 @@ export const load: LayoutLoad = async ({ depends, url }) => {
return {
account,
- organizations: await sdk.forConsole.teams.list()
+ organizations: await sdk.forConsole.billing.listOrganization()
};
} catch (error) {
const acceptedRoutes = [
diff --git a/src/routes/console/account/organizations/+page.ts b/src/routes/console/account/organizations/+page.ts
index 0b89b1d302..3f21115b89 100644
--- a/src/routes/console/account/organizations/+page.ts
+++ b/src/routes/console/account/organizations/+page.ts
@@ -12,7 +12,7 @@ export const load: PageLoad = async ({ url, route }) => {
return {
offset,
limit,
- organizations: await sdk.forConsole.teams.list([
+ organizations: await sdk.forConsole.billing.listOrganization([
Query.offset(offset),
Query.limit(limit),
Query.orderDesc('')
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index 1b9dd8b458..3bcbae0413 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -22,8 +22,13 @@
import type { Coupon, PaymentList } from '$lib/sdk/billing';
import { plansInfo, tierFree, tierPro, tierToPlan } from '$lib/stores/billing';
import { addNotification } from '$lib/stores/notifications';
- import { organizationList, type Organization } from '$lib/stores/organization';
+ import {
+ organizationList,
+ type CreateOrgAuth,
+ type Organization
+ } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
+ import { confirmPayment } from '$lib/stores/stripe';
import { ID } from '@appwrite.io/console';
import { onMount } from 'svelte';
import { writable } from 'svelte/store';
@@ -90,9 +95,13 @@
paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
}
+ function isOrganization(org: Organization | CreateOrgAuth): org is Organization {
+ return (org as Organization).$id !== undefined;
+ }
+
async function create() {
try {
- let org: Organization;
+ let org: Organization | CreateOrgAuth;
if (billingPlan === BillingPlan.FREE) {
org = await sdk.forConsole.billing.createOrganization(
@@ -113,8 +122,14 @@
collaborators
);
+ if (!isOrganization(org) && org.status == 402) {
+ let clientSecret = org.clientSecret;
+ await confirmPayment('', clientSecret, paymentMethodId);
+ // throw new Error('Payment requires authentication');
+ }
+
//Add budget
- if (billingBudget) {
+ if (billingBudget && isOrganization(org)) {
await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]);
}
From eec5c6f1f34b5fb5e0d788166a3e92eae9819ef5 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Thu, 29 Aug 2024 08:30:49 +0545
Subject: [PATCH 03/39] support taxid and budget while creating
---
src/lib/sdk/billing.ts | 8 ++++++--
.../console/create-organization/+page.svelte | 16 +++++++++-------
2 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index ea278c5bac..936d9f3ad8 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -309,7 +309,9 @@ export class Billing {
paymentMethodId: string,
billingAddressId: string = undefined,
couponId: string = undefined,
- invites: Array = []
+ invites: Array = [],
+ budget: number = undefined,
+ taxId: string = undefined
): Promise {
const path = `/organizations`;
const params = {
@@ -319,7 +321,9 @@ export class Billing {
paymentMethodId,
billingAddressId,
couponId,
- invites
+ invites,
+ budget,
+ taxId
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index 3bcbae0413..09c9e9248b 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -119,7 +119,9 @@
paymentMethodId,
null,
couponData?.code,
- collaborators
+ collaborators,
+ billingBudget,
+ taxId
);
if (!isOrganization(org) && org.status == 402) {
@@ -129,9 +131,9 @@
}
//Add budget
- if (billingBudget && isOrganization(org)) {
- await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]);
- }
+ // if (billingBudget && isOrganization(org)) {
+ // await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]);
+ // }
// //Add coupon
// if (couponData?.code) {
@@ -154,9 +156,9 @@
// }
// Add tax ID
- if (taxId) {
- await sdk.forConsole.billing.updateTaxId(org.$id, taxId);
- }
+ // if (taxId) {
+ // await sdk.forConsole.billing.updateTaxId(org.$id, taxId);
+ // }
}
trackEvent(Submit.OrganizationCreate, {
From 414bc60bc88ef93dd87c4023dde3e7e55898c0b1 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Thu, 29 Aug 2024 11:26:22 +0545
Subject: [PATCH 04/39] handle validation
---
src/lib/sdk/billing.ts | 26 ++++++++-
src/lib/stores/stripe.ts | 10 +++-
.../console/create-organization/+page.svelte | 56 ++++++++++++++++---
.../billing/paymentHistory.svelte | 1 -
4 files changed, 77 insertions(+), 16 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index 936d9f3ad8..646fdc1752 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -302,16 +302,36 @@ export class Billing {
);
}
+ async validateOrganization(
+ organizationId: string,
+ invites: string[],
+ ): Promise {
+ const path = `/organizations/${organizationId}/validate`;
+ const params = {
+ organizationId,
+ invites,
+ };
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'PATCH',
+ uri,
+ {
+ 'content-type': 'application/json'
+ },
+ params
+ );
+ }
+
async createOrganization(
organizationId: string,
name: string,
billingPlan: string,
paymentMethodId: string,
- billingAddressId: string = undefined,
- couponId: string = undefined,
+ billingAddressId: string = null,
+ couponId: string = null,
invites: Array = [],
budget: number = undefined,
- taxId: string = undefined
+ taxId: string = null
): Promise {
const path = `/organizations`;
const params = {
diff --git a/src/lib/stores/stripe.ts b/src/lib/stores/stripe.ts
index 93b4576aec..b1f01016b8 100644
--- a/src/lib/stores/stripe.ts
+++ b/src/lib/stores/stripe.ts
@@ -116,7 +116,8 @@ export async function confirmPayment(
orgId: string,
clientSecret: string,
paymentMethodId: string,
- route?: string
+ route?: string,
+ returnError: boolean = false
) {
try {
const url =
@@ -128,10 +129,13 @@ export async function confirmPayment(
clientSecret: clientSecret,
confirmParams: {
return_url: url,
- payment_method: paymentMethod.providerMethodId
- }
+ payment_method: paymentMethod.providerMethodId,
+ },
});
if (error) {
+ if (returnError) {
+ return error;
+ }
throw error.message;
}
} catch (e) {
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index 09c9e9248b..67d1341f15 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -88,6 +88,14 @@
if (anyOrgFree) {
billingPlan = BillingPlan.PRO;
}
+ if($page.url.searchParams.has('type')) {
+ const type = $page.url.searchParams.get('type');
+ if(type === 'confirmed') {
+ const organizationId= $page.url.searchParams.get('id');
+ const invites = $page.url.searchParams.getAll('invites');
+ await validate(organizationId, invites);
+ }
+ }
});
async function loadPaymentMethods() {
@@ -99,6 +107,27 @@
return (org as Organization).$id !== undefined;
}
+ async function validate(organizationId: string, invites: string[]) {
+ try {
+ let org = await sdk.forConsole.billing.validateOrganization(organizationId, invites);
+ if (isOrganization(org)) {
+ await preloadData(`${base}/console/organization-${org.$id}`);
+ await goto(`${base}/console/organization-${org.$id}`);
+ addNotification({
+ type: 'success',
+ message: `${org.name ?? 'Organization'} has been created`
+ });
+ }
+ } catch (e) {
+ addNotification({
+ type: 'error',
+ message: e.message
+ });
+ trackError(e, Submit.OrganizationCreate);
+ }
+
+ }
+
async function create() {
try {
let org: Organization | CreateOrgAuth;
@@ -126,8 +155,15 @@
if (!isOrganization(org) && org.status == 402) {
let clientSecret = org.clientSecret;
- await confirmPayment('', clientSecret, paymentMethodId);
- // throw new Error('Payment requires authentication');
+ let params = new URLSearchParams();
+ params.append('type', 'confirmed');
+ params.append('id', org.teamId);
+ for (let index = 0; index < collaborators.length; index++) {
+ const invite = collaborators[index];
+ params.append('invites', invite);
+ }
+ await confirmPayment('', clientSecret, paymentMethodId, '/console/create-organization?'+params.toString());
+ await validate(org.teamId, collaborators);
}
//Add budget
@@ -167,13 +203,15 @@
members_invited: collaborators?.length
});
- await invalidate(Dependencies.ACCOUNT);
- await preloadData(`${base}/console/organization-${org.$id}`);
- await goto(`${base}/console/organization-${org.$id}`);
- addNotification({
- type: 'success',
- message: `${name ?? 'Organization'} has been created`
- });
+ if(isOrganization(org)) {
+ await invalidate(Dependencies.ACCOUNT);
+ await preloadData(`${base}/console/organization-${org.$id}`);
+ await goto(`${base}/console/organization-${org.$id}`);
+ addNotification({
+ type: 'success',
+ message: `${org.name ?? 'Organization'} has been created`
+ });
+ }
} catch (e) {
addNotification({
type: 'error',
diff --git a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte
index 1784b0a57d..0c9642dfca 100644
--- a/src/routes/console/organization-[organization]/billing/paymentHistory.svelte
+++ b/src/routes/console/organization-[organization]/billing/paymentHistory.svelte
@@ -49,7 +49,6 @@
invoiceList = await sdk.forConsole.billing.listInvoices($page.params.organization, [
Query.limit(limit),
Query.offset(offset),
- Query.notEqual('from', $organization.billingCurrentInvoiceDate),
Query.orderDesc('$createdAt')
]);
}
From c97e372386764d6cd456e9cf776368f1c4f3fa26 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Tue, 3 Sep 2024 09:17:18 +0545
Subject: [PATCH 05/39] fix check with cloud
---
src/lib/sdk/billing.ts | 4 +-
src/lib/stores/organization.ts | 2 +-
src/routes/+layout.ts | 3 +-
.../console/account/organizations/+page.ts | 15 ++++--
.../console/create-organization/+page.svelte | 52 +++++--------------
5 files changed, 28 insertions(+), 48 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index 646fdc1752..3c93d32aec 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -1,5 +1,5 @@
import type { Client, Models } from '@appwrite.io/console';
-import type { CreateOrgAuth, Organization, OrganizationList } from '../stores/organization';
+import type { OrganizationError, Organization, OrganizationList } from '../stores/organization';
import type { PaymentMethod } from '@stripe/stripe-js';
import type { Tier } from '$lib/stores/billing';
@@ -332,7 +332,7 @@ export class Billing {
invites: Array = [],
budget: number = undefined,
taxId: string = null
- ): Promise {
+ ): Promise {
const path = `/organizations`;
const params = {
organizationId,
diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts
index d41cc3f54a..ca7269ca37 100644
--- a/src/lib/stores/organization.ts
+++ b/src/lib/stores/organization.ts
@@ -3,7 +3,7 @@ import { derived, writable } from 'svelte/store';
import type { Models } from '@appwrite.io/console';
import type { Tier } from './billing';
-export type CreateOrgAuth = {
+export type OrganizationError = {
status: number;
message: string;
teamId: string;
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 5f0472229f..8986f1a126 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -6,6 +6,7 @@ import { redirect } from '@sveltejs/kit';
import { Dependencies } from '$lib/constants';
import type { LayoutLoad } from './$types';
import { redirectTo } from './store';
+import { isCloud } from '$lib/system';
export const ssr = false;
@@ -22,7 +23,7 @@ export const load: LayoutLoad = async ({ depends, url }) => {
return {
account,
- organizations: await sdk.forConsole.billing.listOrganization()
+ organizations: isCloud ? await sdk.forConsole.billing.listOrganization() : await sdk.forConsole.teams.list()
};
} catch (error) {
const acceptedRoutes = [
diff --git a/src/routes/console/account/organizations/+page.ts b/src/routes/console/account/organizations/+page.ts
index 3f21115b89..803497c6a8 100644
--- a/src/routes/console/account/organizations/+page.ts
+++ b/src/routes/console/account/organizations/+page.ts
@@ -3,19 +3,24 @@ import { sdk } from '$lib/stores/sdk';
import { getLimit, getPage, pageToOffset } from '$lib/helpers/load';
import { CARD_LIMIT } from '$lib/constants';
import type { PageLoad } from './$types';
+import { isCloud } from '$lib/system';
export const load: PageLoad = async ({ url, route }) => {
const page = getPage(url);
const limit = getLimit(url, route, CARD_LIMIT);
const offset = pageToOffset(page, limit);
+ const queries = [
+ Query.offset(offset),
+ Query.limit(limit),
+ Query.orderDesc('')
+ ];
+
+ const organizations = isCloud ? await sdk.forConsole.billing.listOrganization(queries) : sdk.forConsole.teams.list(queries);
+
return {
offset,
limit,
- organizations: await sdk.forConsole.billing.listOrganization([
- Query.offset(offset),
- Query.limit(limit),
- Query.orderDesc('')
- ])
+ organizations
};
};
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index 67d1341f15..323d48c610 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -24,7 +24,7 @@
import { addNotification } from '$lib/stores/notifications';
import {
organizationList,
- type CreateOrgAuth,
+ type OrganizationError,
type Organization
} from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
@@ -88,10 +88,10 @@
if (anyOrgFree) {
billingPlan = BillingPlan.PRO;
}
- if($page.url.searchParams.has('type')) {
+ if ($page.url.searchParams.has('type')) {
const type = $page.url.searchParams.get('type');
- if(type === 'confirmed') {
- const organizationId= $page.url.searchParams.get('id');
+ if (type === 'confirmed') {
+ const organizationId = $page.url.searchParams.get('id');
const invites = $page.url.searchParams.getAll('invites');
await validate(organizationId, invites);
}
@@ -103,7 +103,7 @@
paymentMethodId = methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
}
- function isOrganization(org: Organization | CreateOrgAuth): org is Organization {
+ function isOrganization(org: Organization | OrganizationError): org is Organization {
return (org as Organization).$id !== undefined;
}
@@ -125,12 +125,11 @@
});
trackError(e, Submit.OrganizationCreate);
}
-
}
async function create() {
try {
- let org: Organization | CreateOrgAuth;
+ let org: Organization | OrganizationError;
if (billingPlan === BillingPlan.FREE) {
org = await sdk.forConsole.billing.createOrganization(
@@ -162,39 +161,14 @@
const invite = collaborators[index];
params.append('invites', invite);
}
- await confirmPayment('', clientSecret, paymentMethodId, '/console/create-organization?'+params.toString());
+ await confirmPayment(
+ '',
+ clientSecret,
+ paymentMethodId,
+ '/console/create-organization?' + params.toString()
+ );
await validate(org.teamId, collaborators);
}
-
- //Add budget
- // if (billingBudget && isOrganization(org)) {
- // await sdk.forConsole.billing.updateBudget(org.$id, billingBudget, [75]);
- // }
-
- // //Add coupon
- // if (couponData?.code) {
- // await sdk.forConsole.billing.addCredit(org.$id, couponData.code);
- // trackEvent(Submit.CreditRedeem);
- // }
-
- // //Add collaborators
- // if (collaborators?.length) {
- // collaborators.forEach(async (collaborator) => {
- // await sdk.forConsole.teams.createMembership(
- // org.$id,
- // ['owner'],
- // collaborator,
- // undefined,
- // undefined,
- // `${$page.url.origin}/console/organization-${org.$id}`
- // );
- // });
- // }
-
- // Add tax ID
- // if (taxId) {
- // await sdk.forConsole.billing.updateTaxId(org.$id, taxId);
- // }
}
trackEvent(Submit.OrganizationCreate, {
@@ -203,7 +177,7 @@
members_invited: collaborators?.length
});
- if(isOrganization(org)) {
+ if (isOrganization(org)) {
await invalidate(Dependencies.ACCOUNT);
await preloadData(`${base}/console/organization-${org.$id}`);
await goto(`${base}/console/organization-${org.$id}`);
From b568e8553c5eae5a308073a78815015e6e329820 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Tue, 3 Sep 2024 09:19:07 +0545
Subject: [PATCH 06/39] improve
---
src/routes/console/create-organization/+page.svelte | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/routes/console/create-organization/+page.svelte b/src/routes/console/create-organization/+page.svelte
index 323d48c610..8dc928f004 100644
--- a/src/routes/console/create-organization/+page.svelte
+++ b/src/routes/console/create-organization/+page.svelte
@@ -90,7 +90,7 @@
}
if ($page.url.searchParams.has('type')) {
const type = $page.url.searchParams.get('type');
- if (type === 'confirmed') {
+ if (type === 'payment_confirmed') {
const organizationId = $page.url.searchParams.get('id');
const invites = $page.url.searchParams.getAll('invites');
await validate(organizationId, invites);
@@ -155,7 +155,7 @@
if (!isOrganization(org) && org.status == 402) {
let clientSecret = org.clientSecret;
let params = new URLSearchParams();
- params.append('type', 'confirmed');
+ params.append('type', 'payment_confirmed');
params.append('id', org.teamId);
for (let index = 0; index < collaborators.length; index++) {
const invite = collaborators[index];
From 81d4ad8a6e2a5939edd15ffd5298f20e0ecdcbe1 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 11 Nov 2024 08:41:25 +0000
Subject: [PATCH 07/39] remove unused
---
.../organization-[organization]/billing/paymentHistory.svelte | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
index 290b76b75b..e74739f537 100644
--- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
@@ -28,7 +28,6 @@
import { onMount } from 'svelte';
import { trackEvent } from '$lib/actions/analytics';
import { selectedInvoice, showRetryModal } from './store';
- import { organization } from '$lib/stores/organization';
let showDropdown = [];
let showFailedError = false;
From c7a9e26de0ee343bc66e835b58533d5c7ec23ff9 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 11 Nov 2024 09:05:36 +0000
Subject: [PATCH 08/39] allow scale selection
---
.../components/billing/planSelection.svelte | 50 +++++++++----------
1 file changed, 24 insertions(+), 26 deletions(-)
diff --git a/src/lib/components/billing/planSelection.svelte b/src/lib/components/billing/planSelection.svelte
index 0d484a9b40..cfcb28bbab 100644
--- a/src/lib/components/billing/planSelection.svelte
+++ b/src/lib/components/billing/planSelection.svelte
@@ -76,31 +76,29 @@
- {#if $organization?.billingPlan === BillingPlan.SCALE}
-
-
-
-
-
- {tierScale.name}
- {#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg}
- Current plan
- {/if}
-
-
- {tierScale.description}
-
-
- {formatCurrency(scalePlan?.price ?? 0)} per month + usage
-
-
-
-
-
- {/if}
+
+
+
+
+
+ {tierScale.name}
+ {#if $organization?.billingPlan === BillingPlan.SCALE && !isNewOrg}
+ Current plan
+ {/if}
+
+
+ {tierScale.description}
+
+
+ {formatCurrency(scalePlan?.price ?? 0)} per month + usage
+
+
+
+
+
{/if}
From f29ca9a8e9776e643aad723c268bb549d1a63f34 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Thu, 14 Nov 2024 12:59:39 +0545
Subject: [PATCH 09/39] update plan upgrade
---
src/lib/sdk/billing.ts | 14 ++-
.../change-plan/+page.svelte | 116 +++++++++++-------
2 files changed, 86 insertions(+), 44 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index f2428fd19d..bee94ffc3b 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -416,14 +416,22 @@ export class Billing {
organizationId: string,
billingPlan: string,
paymentMethodId: string,
- billingAddressId: string = undefined
- ): Promise {
+ billingAddressId: string = undefined,
+ couponId: string = null,
+ invites: Array = [],
+ budget: number = undefined,
+ taxId: string = null
+ ): Promise {
const path = `/organizations/${organizationId}/plan`;
const params = {
organizationId,
billingPlan,
paymentMethodId,
- billingAddressId
+ billingAddressId,
+ couponId,
+ invites,
+ budget,
+ taxId
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index 3682491c7f..573f1e9fb2 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -1,5 +1,5 @@
-
- {currentPlan.name} plan
- {formatCurrency(currentPlan.price)}
-
-
+
+
{selectedPlan.name} plan
+
{formatCurrency(selectedPlan.price)}
+
+
+
Additional seats ({collaborators?.length})
- {formatCurrency(extraSeatsCost)}
+ {formatCurrency(
+ isScaleDowngrade
+ ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0)
+ : extraSeatsCost
+ )}
-
+
+
+ {#if isScaleUpgrade}
+ {@const currentPlanName = currentOrgPlan.name}
+
+
+ Unused {currentPlanName} plan balance
+
+
+
+
-{formatCurrency(unUsedBalances)}
+
+ {:else if isScaleDowngrade}
+
+
Unused {currentOrgPlan.name} plan balance
+
-{formatCurrency(currentOrgPlan.price)}
+
+ {/if}
+
{#if couponData?.status === 'active'}
{/if}
-
+
Upcoming chargeDue on {!currentPlan.trialDays
+ >Due on {!selectedPlan.trialDays
? toLocaleDate(billingPayDate.toString())
: toLocaleDate(trialEndDate.toString())}
{formatCurrency(estimatedTotal)}
-
+
- You'll pay {formatCurrency(estimatedTotal)} now, with our first
- billing cycle starting on
+ You'll {isRefund ? 'receive a refund of' : 'pay'}
+ {formatCurrency(estimatedTotal)}
+ now, with our first billing cycle starting on
{!currentPlan.trialDays
+ >{!selectedPlan.trialDays
? toLocaleDate(billingPayDate.toString())
: toLocaleDate(trialEndDate.toString())} . Once your credits run out, you'll be charged
- {formatCurrency(currentPlan.price)} plus usage fees every 30 days.
+ {formatCurrency(selectedPlan.price)} plus usage fees every 30 days.
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index fe317b18a4..46c1e8b59e 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -23,7 +23,7 @@
InputTextarea,
Label
} from '$lib/elements/forms';
- import { formatCurrency } from '$lib/helpers/numbers.js';
+ import { formatCurrency } from '$lib/helpers/numbers';
import {
WizardSecondaryContainer,
WizardSecondaryContent,
@@ -39,7 +39,7 @@
type OrganizationError
} from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
- import { confirmPayment } from '$lib/stores/stripe.js';
+ import { confirmPayment } from '$lib/stores/stripe';
import { user } from '$lib/stores/user';
import { VARS } from '$lib/system';
import { onMount } from 'svelte';
@@ -107,8 +107,8 @@
billingPlan = BillingPlan.PRO;
}
- const currentPlan = await sdk.forConsole.billing.getPlan($organization?.$id);
- selfService = currentPlan.selfService;
+ const currentOrgPlan = await sdk.forConsole.billing.getPlan($organization?.$id);
+ selfService = currentOrgPlan.selfService;
});
async function loadPaymentMethods() {
@@ -210,7 +210,7 @@
async function upgrade() {
try {
//Add collaborators
- var newCollaborators = [];
+ let newCollaborators = [];
if (collaborators?.length) {
newCollaborators = collaborators.filter(
(collaborator) =>
@@ -369,11 +369,12 @@
{#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM}
+ currentTier={$organization.billingPlan} />
{:else if $organization.billingPlan !== BillingPlan.CUSTOM}
{/if}
From bcbf5c75b5faa7ee1b82b3c0192949d586774809 Mon Sep 17 00:00:00 2001
From: Darshan
Date: Thu, 19 Dec 2024 13:25:27 +0530
Subject: [PATCH 13/39] address comments.
---
.../billing/estimatedTotalBox.svelte | 45 ++++++++++---------
1 file changed, 25 insertions(+), 20 deletions(-)
diff --git a/src/lib/components/billing/estimatedTotalBox.svelte b/src/lib/components/billing/estimatedTotalBox.svelte
index df06ef0b73..b73c87378c 100644
--- a/src/lib/components/billing/estimatedTotalBox.svelte
+++ b/src/lib/components/billing/estimatedTotalBox.svelte
@@ -34,17 +34,14 @@
: 0;
$: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0);
- $: grossCost =
- isScaleUpgrade || isScaleDowngrade
- ? selectedPlan.price + extraSeatsCost - unUsedBalances
- : selectedPlan.price + extraSeatsCost;
+ $: grossCost = isScaleUpgrade
+ ? selectedPlan.price + extraSeatsCost - unUsedBalances
+ : selectedPlan.price + extraSeatsCost;
$: estimatedTotal =
couponData?.status === 'active' ? Math.max(0, grossCost - couponData.credits) : grossCost;
$: trialEndDate = new Date(
billingPayDate.getTime() + selectedPlan.trialDays * 24 * 60 * 60 * 1000
);
-
- $: isRefund = isScaleDowngrade && grossCost < 0;
-{formatCurrency(unUsedBalances)}
- {:else if isScaleDowngrade}
-
-
Unused {currentOrgPlan.name} plan balance
-
-{formatCurrency(currentOrgPlan.price)}
-
{/if}
{#if couponData?.status === 'active'}
@@ -107,15 +99,28 @@
- You'll {isRefund ? 'receive a refund of' : 'pay'}
- {formatCurrency(estimatedTotal)}
- now, with our first billing cycle starting on
- {!selectedPlan.trialDays
- ? toLocaleDate(billingPayDate.toString())
- : toLocaleDate(trialEndDate.toString())} . Once your credits run out, you'll be charged
- {formatCurrency(selectedPlan.price)} plus usage fees every 30 days.
+ {#if isScaleDowngrade}
+ You'll continue using the {currentOrgPlan.name} plan until your current cycle ends on
+ {!selectedPlan.trialDays
+ ? toLocaleDate(billingPayDate.toString())
+ : toLocaleDate(trialEndDate.toString())} . Starting the next cycle, your plan will switch to {selectedPlan.name}, and you'll be
+ charged
+ {formatCurrency(grossCost)}
+ every 30 days.
+ {:else}
+ You'll pay
+ {formatCurrency(estimatedTotal)}
+ now, with our first billing cycle starting on
+ {!selectedPlan.trialDays
+ ? toLocaleDate(billingPayDate.toString())
+ : toLocaleDate(trialEndDate.toString())} . Once your credits run out, you'll be charged
+ {formatCurrency(selectedPlan.price)} plus usage fees every 30
+ days.
+ {/if}
From b6a517a8cf952c9d3ba5d982a34e7c4f23935dff Mon Sep 17 00:00:00 2001
From: Darshan
Date: Thu, 19 Dec 2024 13:25:35 +0530
Subject: [PATCH 14/39] ran: formatter.
---
src/lib/components/billing/planSelection.svelte | 6 +-----
src/lib/sdk/billing.ts | 7 ++-----
src/lib/stores/stripe.ts | 4 ++--
src/routes/(console)/account/organizations/+page.ts | 10 ++++------
src/routes/+layout.ts | 4 +++-
5 files changed, 12 insertions(+), 19 deletions(-)
diff --git a/src/lib/components/billing/planSelection.svelte b/src/lib/components/billing/planSelection.svelte
index cfcb28bbab..4a6e1f7caf 100644
--- a/src/lib/components/billing/planSelection.svelte
+++ b/src/lib/components/billing/planSelection.svelte
@@ -77,11 +77,7 @@
-
+
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index bee94ffc3b..57ad227be1 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -318,14 +318,11 @@ export class Billing {
);
}
- async validateOrganization(
- organizationId: string,
- invites: string[],
- ): Promise {
+ async validateOrganization(organizationId: string, invites: string[]): Promise {
const path = `/organizations/${organizationId}/validate`;
const params = {
organizationId,
- invites,
+ invites
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
diff --git a/src/lib/stores/stripe.ts b/src/lib/stores/stripe.ts
index 3579746463..e62110d209 100644
--- a/src/lib/stores/stripe.ts
+++ b/src/lib/stores/stripe.ts
@@ -130,8 +130,8 @@ export async function confirmPayment(
clientSecret: clientSecret,
confirmParams: {
return_url: url,
- payment_method: paymentMethod.providerMethodId,
- },
+ payment_method: paymentMethod.providerMethodId
+ }
});
if (error) {
if (returnError) {
diff --git a/src/routes/(console)/account/organizations/+page.ts b/src/routes/(console)/account/organizations/+page.ts
index 803497c6a8..237a3772d7 100644
--- a/src/routes/(console)/account/organizations/+page.ts
+++ b/src/routes/(console)/account/organizations/+page.ts
@@ -10,13 +10,11 @@ export const load: PageLoad = async ({ url, route }) => {
const limit = getLimit(url, route, CARD_LIMIT);
const offset = pageToOffset(page, limit);
- const queries = [
- Query.offset(offset),
- Query.limit(limit),
- Query.orderDesc('')
- ];
+ const queries = [Query.offset(offset), Query.limit(limit), Query.orderDesc('')];
- const organizations = isCloud ? await sdk.forConsole.billing.listOrganization(queries) : sdk.forConsole.teams.list(queries);
+ const organizations = isCloud
+ ? await sdk.forConsole.billing.listOrganization(queries)
+ : sdk.forConsole.teams.list(queries);
return {
offset,
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index 6468cab571..4c9b760ca7 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -29,7 +29,9 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
if (account) {
return {
account,
- organizations: isCloud ? await sdk.forConsole.billing.listOrganization() : await sdk.forConsole.teams.list()
+ organizations: isCloud
+ ? await sdk.forConsole.billing.listOrganization()
+ : await sdk.forConsole.teams.list()
};
}
From 867320911c202c46e618cc904818a092b0a3c141 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Sun, 22 Dec 2024 13:14:06 +0545
Subject: [PATCH 15/39] update models
---
src/lib/sdk/billing.ts | 24 ++++++++++++++++++------
src/lib/stores/organization.ts | 2 ++
2 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index bee94ffc3b..01e2008a5f 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -174,6 +174,10 @@ export type Aggregation = {
* Usage logs for the billing period.
*/
resources: OrganizationUsage;
+ /**
+ * Aggregation billing plan
+ */
+ plan: string;
};
export type OrganizationUsage = {
@@ -388,19 +392,27 @@ export class Billing {
);
}
- async getPlan(organizationId: string): Promise {
+ async getOrganizationPlan(organizationId: string): Promise {
const path = `/organizations/${organizationId}/plan`;
- const params = {
- organizationId
- };
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'get',
uri,
{
'content-type': 'application/json'
- },
- params
+ }
+ );
+ }
+
+ async getPlan(planId: string): Promise {
+ const path = `/console/plans/${planId}`;
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'get',
+ uri,
+ {
+ 'content-type': 'application/json'
+ }
);
}
diff --git a/src/lib/stores/organization.ts b/src/lib/stores/organization.ts
index 0e1912c5fc..53420f4e50 100644
--- a/src/lib/stores/organization.ts
+++ b/src/lib/stores/organization.ts
@@ -29,6 +29,8 @@ export type Organization = Models.Team> & {
amount: number;
billingTaxId?: string;
billingPlanDowngrade?: Tier;
+ billingAggregationId: string;
+ billingInvoiceId: string;
};
export type OrganizationList = {
From 8fdf7c515f5f8470f17723cc7922c5adabf05702 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Sun, 22 Dec 2024 13:15:42 +0545
Subject: [PATCH 16/39] refactor and get current plan from aggregation
---
.../billing/+page.svelte | 3 ++-
.../billing/+page.ts | 25 ++++++++++++++-----
.../billing/planSummary.svelte | 5 ++--
.../change-plan/+page.svelte | 2 +-
.../usage/[[invoice]]/+page.ts | 2 +-
.../storage/bucket-[bucket]/settings/+page.ts | 2 +-
6 files changed, 27 insertions(+), 12 deletions(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte
index d3d6b7fd1a..ad680d21a2 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte
@@ -123,7 +123,8 @@
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts
index 0e945f906a..14957a4d3a 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.ts
+++ b/src/routes/(console)/organization-[organization]/billing/+page.ts
@@ -21,10 +21,16 @@ export const load: PageLoad = async ({ parent, depends }) => {
const billingAddressId = (organization as Organization)?.billingAddressId;
const billingAddressPromise: Promise = billingAddressId
? sdk.forConsole.billing
- .getOrganizationBillingAddress(organization.$id, billingAddressId)
- .catch(() => null)
+ .getOrganizationBillingAddress(organization.$id, billingAddressId)
+ .catch(() => null)
: null;
+ const billingAggregationId = (organization as Organization)?.billingAggregationId;
+ const billingInvoiceId = (organization as Organization)?.billingInvoiceId;
+
+ const billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId);
+ console.log(billingAggregation);
+
const [
paymentMethods,
addressList,
@@ -32,18 +38,22 @@ export const load: PageLoad = async ({ parent, depends }) => {
billingAddress,
currentPlan,
creditList,
- invoices
+ invoices,
+ aggregationBillingPlan,
+ billingInvoice,
] = await Promise.all([
sdk.forConsole.billing.listPaymentMethods(),
sdk.forConsole.billing.listAddresses(),
sdk.forConsole.billing.listAggregation(organization.$id),
billingAddressPromise,
- sdk.forConsole.billing.getPlan(organization.$id),
+ sdk.forConsole.billing.getOrganizationPlan(organization.$id),
sdk.forConsole.billing.listCredits(organization.$id),
sdk.forConsole.billing.listInvoices(organization.$id, [
Query.limit(1),
Query.equal('from', organization.billingCurrentInvoiceDate)
- ])
+ ]),
+ sdk.forConsole.billing.getPlan(billingAggregation.plan),
+ sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId)
]);
return {
@@ -52,7 +62,10 @@ export const load: PageLoad = async ({ parent, depends }) => {
aggregationList,
billingAddress,
currentPlan,
+ aggregationBillingPlan,
creditList,
- invoices
+ invoices,
+ billingAggregation,
+ billingInvoice
};
};
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index c84356b753..f1c6c64650 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -17,8 +17,9 @@
export let members: Models.MembershipList;
export let currentPlan: Plan;
export let creditList: CreditList;
+ export let currentInvoice: Invoice | undefined = undefined
- const currentInvoice: Invoice | undefined = invoices.length > 0 ? invoices[0] : undefined;
+ // const currentInvoice: Invoice | undefined = invoices.length > 0 ? invoices[0] : undefined;
const extraMembers = members.total > 1 ? members.total - 1 : 0;
const availableCredit = creditList.available;
const today = new Date();
@@ -45,7 +46,7 @@
- {tierToPlan($organization?.billingPlan)?.name} plan
+ {currentPlan.name} plan
{isTrial || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION
? formatCurrency(0)
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index fe317b18a4..a44ab8ff08 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -107,7 +107,7 @@
billingPlan = BillingPlan.PRO;
}
- const currentPlan = await sdk.forConsole.billing.getPlan($organization?.$id);
+ const currentPlan = await sdk.forConsole.billing.getOrganizationPlan($organization?.$id);
selfService = currentPlan.selfService;
});
diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts
index 9ffafbac21..b3546b01de 100644
--- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts
+++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/+page.ts
@@ -45,7 +45,7 @@ export const load: PageLoad = async ({ params, parent }) => {
sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]),
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate),
sdk.forConsole.teams.listMemberships(params.organization),
- sdk.forConsole.billing.getPlan(org.$id)
+ sdk.forConsole.billing.getOrganizationPlan(org.$id)
]);
const projectNames: { [key: string]: Models.Project } = {};
diff --git a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts
index 546bfa7a8a..83972d5a6a 100644
--- a/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts
+++ b/src/routes/(console)/project-[project]/storage/bucket-[bucket]/settings/+page.ts
@@ -3,7 +3,7 @@ import { sdk } from '$lib/stores/sdk';
export const load: PageLoad = async ({ parent }) => {
const { organization } = await parent();
- const currentPlan = await sdk.forConsole.billing.getPlan(organization.$id);
+ const currentPlan = await sdk.forConsole.billing.getOrganizationPlan(organization.$id);
return {
currentPlan
};
From 1ee29b20777877ed6472b1aded55122168e716f8 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Sun, 22 Dec 2024 13:55:58 +0545
Subject: [PATCH 17/39] update summary
---
.../organization-[organization]/billing/planSummary.svelte | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index f1c6c64650..2ef69316b7 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -39,7 +39,7 @@
- Billing period: {toLocaleDate($organization?.billingCurrentInvoiceDate)} - {toLocaleDate(
+ Due at: {toLocaleDate(
$organization?.billingNextInvoiceDate
)}
From 16705d38aac193517c7de52b730acd12e17f040a Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 23 Dec 2024 07:11:16 +0545
Subject: [PATCH 18/39] fix rename
---
src/routes/(console)/organization-[organization]/+layout.ts | 2 +-
src/routes/(console)/project-[project]/+layout.ts | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/routes/(console)/organization-[organization]/+layout.ts b/src/routes/(console)/organization-[organization]/+layout.ts
index 650990e866..cd1968ea8e 100644
--- a/src/routes/(console)/organization-[organization]/+layout.ts
+++ b/src/routes/(console)/organization-[organization]/+layout.ts
@@ -27,7 +27,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
const res = await sdk.forConsole.billing.getRoles(params.organization);
roles = res.roles;
scopes = res.scopes;
- currentPlan = await sdk.forConsole.billing.getPlan(params.organization);
+ currentPlan = await sdk.forConsole.billing.getOrganizationPlan(params.organization);
if (scopes.includes('billing.read')) {
await failedInvoice.load(params.organization);
if (get(failedInvoice)) {
diff --git a/src/routes/(console)/project-[project]/+layout.ts b/src/routes/(console)/project-[project]/+layout.ts
index 018462d75a..8725851436 100644
--- a/src/routes/(console)/project-[project]/+layout.ts
+++ b/src/routes/(console)/project-[project]/+layout.ts
@@ -29,7 +29,7 @@ export const load: LayoutLoad = async ({ params, depends }) => {
let roles = isCloud ? [] : defaultRoles;
let scopes = isCloud ? [] : defaultScopes;
if (isCloud) {
- currentPlan = await sdk.forConsole.billing.getPlan(project.teamId);
+ currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId);
const res = await sdk.forConsole.billing.getRoles(project.teamId);
roles = res.roles;
scopes = res.scopes;
From 14a0cacbf68c0e41ec36ef82e32c2ef90489d370 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 23 Dec 2024 08:17:14 +0545
Subject: [PATCH 19/39] refactor
---
.../organization-[organization]/billing/+page.svelte | 3 +--
.../(console)/organization-[organization]/billing/+page.ts | 6 ------
.../organization-[organization]/billing/planSummary.svelte | 3 +--
3 files changed, 2 insertions(+), 10 deletions(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte
index ad680d21a2..bf09c55759 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte
@@ -124,8 +124,7 @@
creditList={data?.creditList}
members={data?.members}
currentPlan={data?.aggregationBillingPlan}
- currentInvoice={data?.billingInvoice}
- invoices={data?.invoices.invoices} />
+ currentInvoice={data?.billingInvoice} />
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts
index c98183028b..25c390c2a4 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.ts
+++ b/src/routes/(console)/organization-[organization]/billing/+page.ts
@@ -36,7 +36,6 @@ export const load: PageLoad = async ({ parent, depends }) => {
aggregationList,
billingAddress,
creditList,
- invoices,
aggregationBillingPlan,
billingInvoice,
] = await Promise.all([
@@ -45,10 +44,6 @@ export const load: PageLoad = async ({ parent, depends }) => {
sdk.forConsole.billing.listAggregation(organization.$id),
billingAddressPromise,
sdk.forConsole.billing.listCredits(organization.$id),
- sdk.forConsole.billing.listInvoices(organization.$id, [
- Query.limit(1),
- Query.equal('from', organization.billingCurrentInvoiceDate)
- ]),
sdk.forConsole.billing.getPlan(billingAggregation.plan),
sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId)
]);
@@ -60,7 +55,6 @@ export const load: PageLoad = async ({ parent, depends }) => {
billingAddress,
aggregationBillingPlan,
creditList,
- invoices,
billingAggregation,
billingInvoice
};
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index 2ef69316b7..eeaee9aba5 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -3,7 +3,7 @@
import { CardGrid, Collapsible, CollapsibleItem, Heading } from '$lib/components';
import { Button } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
- import { plansInfo, tierToPlan, upgradeURL } from '$lib/stores/billing';
+ import { plansInfo, upgradeURL } from '$lib/stores/billing';
import { organization } from '$lib/stores/organization';
import type { CreditList, Invoice, Plan } from '$lib/sdk/billing';
import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers';
@@ -13,7 +13,6 @@
import { tooltip } from '$lib/actions/tooltip';
import { type Models } from '@appwrite.io/console';
- export let invoices: Array;
export let members: Models.MembershipList;
export let currentPlan: Plan;
export let creditList: CreditList;
From 9f517bd0681a462a6d23c3dacd7011ac8e1be843 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 23 Dec 2024 08:38:16 +0545
Subject: [PATCH 20/39] improvements on error
---
.../billing/+page.ts | 21 ++++++++++++-------
.../billing/planSummary.svelte | 2 +-
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts
index 25c390c2a4..12db3b5479 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.ts
+++ b/src/routes/(console)/organization-[organization]/billing/+page.ts
@@ -4,7 +4,6 @@ import type { Organization } from '$lib/stores/organization';
import { sdk } from '$lib/stores/sdk';
import { redirect } from '@sveltejs/kit';
import type { PageLoad } from './$types';
-import { Query } from '@appwrite.io/console';
export const load: PageLoad = async ({ parent, depends }) => {
const { organization, scopes } = await parent();
@@ -26,32 +25,40 @@ export const load: PageLoad = async ({ parent, depends }) => {
: null;
const billingAggregationId = (organization as Organization)?.billingAggregationId;
+
+ let billingAggregation = null;
+ try {
+ billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId);
+ } catch (e) {
+ // ignore error
+ }
+
const billingInvoiceId = (organization as Organization)?.billingInvoiceId;
+ let billingInvoice = null;
+ try {
+ billingInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId)
+ } catch (e) {
+ // ignore error
+ }
- const billingAggregation = await sdk.forConsole.billing.getAggregation(organization.$id, billingAggregationId);
const [
paymentMethods,
addressList,
- aggregationList,
billingAddress,
creditList,
aggregationBillingPlan,
- billingInvoice,
] = await Promise.all([
sdk.forConsole.billing.listPaymentMethods(),
sdk.forConsole.billing.listAddresses(),
- sdk.forConsole.billing.listAggregation(organization.$id),
billingAddressPromise,
sdk.forConsole.billing.listCredits(organization.$id),
sdk.forConsole.billing.getPlan(billingAggregation.plan),
- sdk.forConsole.billing.getInvoice(organization.$id, billingInvoiceId)
]);
return {
paymentMethods,
addressList,
- aggregationList,
billingAddress,
aggregationBillingPlan,
creditList,
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index eeaee9aba5..d642ae1087 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -54,7 +54,7 @@
: ''}
- {#if $organization?.billingPlan !== BillingPlan.FREE && $organization?.billingPlan !== BillingPlan.GITHUB_EDUCATION && extraUsage > 0}
+ {#if currentPlan.budgeting && extraUsage > 0}
Add-ons
Date: Tue, 24 Dec 2024 07:09:19 +0545
Subject: [PATCH 21/39] credit support from plan
---
src/lib/sdk/billing.ts | 1 +
.../organization-[organization]/billing/planSummary.svelte | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index ef581a0eb7..711be9befd 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -291,6 +291,7 @@ export type Plan = {
backupsEnabled: boolean;
backupPolicies: number;
emailBranding: boolean;
+ supportsCredit: boolean;
};
export type PlansInfo = {
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index 3d05ac3a61..d71c709d87 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -132,7 +132,7 @@
{/if}
- {#if $organization?.billingPlan !== BillingPlan.FREE && availableCredit > 0}
+ {#if currentPlan.supportsCredit && availableCredit > 0}
trackEvent('click_organization_plan_update', {
From b696c6c7de8091035dc8ebd449a854e1f8867b27 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Tue, 24 Dec 2024 07:32:12 +0545
Subject: [PATCH 22/39] option to cancel downgrade
---
src/lib/sdk/billing.ts | 13 +++++
.../billing/+page.ts | 2 +-
.../billing/planSummary.svelte | 51 ++++++++++++-------
.../change-plan/+page.svelte | 2 +
4 files changed, 48 insertions(+), 20 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index 711be9befd..cc26e046db 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -462,6 +462,19 @@ export class Billing {
params
);
}
+ async cancelDowngrade(
+ organizationId: string
+ ): Promise {
+ const path = `/organizations/${organizationId}/plan/cancel`;
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'patch',
+ uri,
+ {
+ 'content-type': 'application/json'
+ }
+ );
+ }
async updateBudget(
organizationId: string,
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.ts b/src/routes/(console)/organization-[organization]/billing/+page.ts
index 12db3b5479..0d7f48a376 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.ts
+++ b/src/routes/(console)/organization-[organization]/billing/+page.ts
@@ -53,7 +53,7 @@ export const load: PageLoad = async ({ parent, depends }) => {
sdk.forConsole.billing.listAddresses(),
billingAddressPromise,
sdk.forConsole.billing.listCredits(organization.$id),
- sdk.forConsole.billing.getPlan(billingAggregation.plan),
+ sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan),
]);
return {
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index d71c709d87..d9b9ddc08d 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -8,17 +8,18 @@
import type { CreditList, Invoice, Plan } from '$lib/sdk/billing';
import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
- import { BillingPlan } from '$lib/constants';
+ import { BillingPlan, Dependencies } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
import { tooltip } from '$lib/actions/tooltip';
import { type Models } from '@appwrite.io/console';
+ import { sdk } from '$lib/stores/sdk';
+ import { invalidate } from '$app/navigation';
export let members: Models.MembershipList;
export let currentPlan: Plan;
export let creditList: CreditList;
- export let currentInvoice: Invoice | undefined = undefined
+ export let currentInvoice: Invoice | undefined = undefined;
- // const currentInvoice: Invoice | undefined = invoices.length > 0 ? invoices[0] : undefined;
const extraMembers = members.total > 1 ? members.total - 1 : 0;
const availableCredit = creditList.available;
const today = new Date();
@@ -27,6 +28,17 @@
$plansInfo.get($organization.billingPlan)?.trialDays;
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0;
+
+ const cancelDowngrade = async () => {
+ await sdk.forConsole.billing.cancelDowngrade(
+ $organization.$id
+ );
+ await invalidate(Dependencies.ORGANIZATION);
+ trackEvent('click_organization_plan_update', {
+ from: 'button',
+ source: 'billing_tab'
+ });
+ };
{#if $organization}
@@ -38,14 +50,11 @@
- Due at: {toLocaleDate(
- $organization?.billingNextInvoiceDate
- )}
+ Due at: {toLocaleDate($organization?.billingNextInvoiceDate)}
-
- {currentPlan.name} plan
+ {currentPlan.name} plan
{isTrial || $organization?.billingPlan === BillingPlan.GITHUB_EDUCATION
? formatCurrency(0)
@@ -204,17 +213,21 @@
{:else}
-
- trackEvent('click_organization_plan_update', {
- from: 'button',
- source: 'billing_tab'
- })}>
- Change plan
-
+ {#if $organization?.billingPlanDowngrade !== null}
+
Cancel change
+ {:else}
+
+ trackEvent('click_organization_plan_update', {
+ from: 'button',
+ source: 'billing_tab'
+ })}>
+ Change plan
+
+ {/if}
View estimated usage
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index 2158fdeb12..8e1a777c92 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -155,6 +155,8 @@
})
});
+ await invalidate(Dependencies.ORGANIZATION);
+
await goto(previousPage);
addNotification({
type: 'success',
From fb926d9d6fb4e02b3506bce632ef6a5be7d12e7b Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Tue, 24 Dec 2024 08:02:47 +0545
Subject: [PATCH 23/39] cancel downgrade
---
.../billing/cancelDowngradeModel.svelte | 51 +++++++++++++++++++
.../billing/planSummary.svelte | 21 +++-----
.../settings/deleteOrganizationModal.svelte | 2 +-
3 files changed, 58 insertions(+), 16 deletions(-)
create mode 100644 src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte
diff --git a/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte b/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte
new file mode 100644
index 0000000000..78785305b1
--- /dev/null
+++ b/src/routes/(console)/organization-[organization]/billing/cancelDowngradeModel.svelte
@@ -0,0 +1,51 @@
+
+
+
+
+
+ Your organization is set to change to
+ {tierToPlan($organization?.billingPlanDowngrade).name}
+ plan on {toLocaleDate($organization.billingNextInvoiceDate)} .
+
+ Are you sure you want to cancel the change?
+
+ (showCancel = false)}>No
+ Yes
+
+
+
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index d9b9ddc08d..09cc3754e5 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -8,18 +8,19 @@
import type { CreditList, Invoice, Plan } from '$lib/sdk/billing';
import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
- import { BillingPlan, Dependencies } from '$lib/constants';
+ import { BillingPlan } from '$lib/constants';
import { trackEvent } from '$lib/actions/analytics';
import { tooltip } from '$lib/actions/tooltip';
import { type Models } from '@appwrite.io/console';
- import { sdk } from '$lib/stores/sdk';
- import { invalidate } from '$app/navigation';
+ import CancelDowngradeModel from './cancelDowngradeModel.svelte';
export let members: Models.MembershipList;
export let currentPlan: Plan;
export let creditList: CreditList;
export let currentInvoice: Invoice | undefined = undefined;
+ let showCancel: boolean = false;
+
const extraMembers = members.total > 1 ? members.total - 1 : 0;
const availableCredit = creditList.available;
const today = new Date();
@@ -28,17 +29,6 @@
$plansInfo.get($organization.billingPlan)?.trialDays;
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0;
-
- const cancelDowngrade = async () => {
- await sdk.forConsole.billing.cancelDowngrade(
- $organization.$id
- );
- await invalidate(Dependencies.ORGANIZATION);
- trackEvent('click_organization_plan_update', {
- from: 'button',
- source: 'billing_tab'
- });
- };
{#if $organization}
@@ -214,7 +204,7 @@
{:else}
{#if $organization?.billingPlanDowngrade !== null}
-
Cancel change
+
(showCancel = true)}>Cancel change
{:else}
{/if}
+
diff --git a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte
index 08e168fe88..78c9e29463 100644
--- a/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte
+++ b/src/routes/(console)/organization-[organization]/settings/deleteOrganizationModal.svelte
@@ -6,7 +6,7 @@
import { members, organization, organizationList } from '$lib/stores/organization';
import { goto, invalidate } from '$app/navigation';
import { base } from '$app/paths';
- import { BillingPlan, Dependencies } from '$lib/constants';
+ import { Dependencies } from '$lib/constants';
import { Submit, trackEvent, trackError } from '$lib/actions/analytics';
import { projects } from '../store';
import { toLocaleDate } from '$lib/helpers/date';
From 81e5d0d47fafe8220fbdf35b1571032e9425b843 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Mon, 30 Dec 2024 02:59:01 +0000
Subject: [PATCH 24/39] refactor types
---
src/lib/components/billing/usageRates.svelte | 6 +++---
src/lib/sdk/billing.ts | 17 +++++++++++++++--
src/lib/stores/billing.ts | 4 ++--
.../billing/planSummary.svelte | 2 +-
.../change-plan/+page.svelte | 2 +-
.../usage/[[invoice]]/totalMembers.svelte | 2 +-
6 files changed, 23 insertions(+), 10 deletions(-)
diff --git a/src/lib/components/billing/usageRates.svelte b/src/lib/components/billing/usageRates.svelte
index c2d5c73ae0..940380613d 100644
--- a/src/lib/components/billing/usageRates.svelte
+++ b/src/lib/components/billing/usageRates.svelte
@@ -81,16 +81,16 @@
{usage.resource}
- {plan[usage.id] || 'Unlimited'}
+ {plan.addons.seats.limit || 0}
{#if !isFree}
- {formatCurrency(plan.addons.member.price)}/{usage?.unit}
+ {formatCurrency(plan.addons.seats.price)}/{usage?.unit}
{/if}
{:else}
- {@const addon = plan.addons[usage.id]}
+ {@const addon = plan.usage[usage.id]}
{usage.resource}
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index cc26e046db..85673c6156 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -257,13 +257,23 @@ export type AdditionalResource = {
multiplier?: number;
};
+export type PlanAddon = {
+ supported: boolean;
+ currency: string;
+ invoiceDesc: string;
+ price: number;
+ limit: number,
+ value: number;
+ type: string;
+
+}
+
export type Plan = {
$id: string;
name: string;
price: number;
bandwidth: number;
storage: number;
- members: number;
webhooks: number;
users: number;
teams: number;
@@ -274,7 +284,7 @@ export type Plan = {
executions: number;
realtime: number;
logs: number;
- addons: {
+ usage: {
bandwidth: AdditionalResource;
executions: AdditionalResource;
member: AdditionalResource;
@@ -282,6 +292,9 @@ export type Plan = {
storage: AdditionalResource;
users: AdditionalResource;
};
+ addons: {
+ seats: PlanAddon
+ }
trialDays: number;
isAvailable: boolean;
selfService: boolean;
diff --git a/src/lib/stores/billing.ts b/src/lib/stores/billing.ts
index c14b4b9494..9e766251e9 100644
--- a/src/lib/stores/billing.ts
+++ b/src/lib/stores/billing.ts
@@ -272,7 +272,7 @@ export async function checkForUsageLimit(org: Organization) {
const members = org.total;
const plan = get(plansInfo)?.get(org.billingPlan);
- const membersOverflow = members > plan.members ? members - (plan.members || members) : 0;
+ const membersOverflow = (members - 1) > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
if (resources.some((r) => r.value >= 100) || membersOverflow > 0) {
readOnly.set(true);
@@ -475,7 +475,7 @@ export function calculateExcess(usage: OrganizationUsage, plan: Plan, members: n
storage: calculateResourceSurplus(usage?.storageTotal, plan.storage, 'GB'),
users: calculateResourceSurplus(usage?.usersTotal, plan.users),
executions: calculateResourceSurplus(usage?.executionsTotal, plan.executions, 'GB'),
- members: calculateResourceSurplus(members, plan.members)
+ members: calculateResourceSurplus(members - 1, plan.addons.seats.limit || 0)
};
}
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index 09cc3754e5..7d032055a9 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -78,7 +78,7 @@
{formatCurrency(
extraMembers *
- (currentPlan?.addons?.member?.price ?? 0)
+ (currentPlan?.usage?.member?.price ?? 0)
)}
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index 8e1a777c92..e1072e2478 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -321,7 +321,7 @@
you will be charged {formatCurrency(
extraMembers *
- ($plansInfo?.get(billingPlan)?.addons?.member?.price ?? 0)
+ ($plansInfo?.get(billingPlan)?.usage?.member?.price ?? 0)
)} monthly for {extraMembers} team members. This will be reflected in
your next invoice.
diff --git a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte
index d63585b52d..b92803eaef 100644
--- a/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte
+++ b/src/routes/(console)/organization-[organization]/usage/[[invoice]]/totalMembers.svelte
@@ -46,7 +46,7 @@
From 34f0727d5fc3689fb75c19dcf45113487c41fc35 Mon Sep 17 00:00:00 2001
From: Darshan
Date: Thu, 9 Jan 2025 11:48:59 +0530
Subject: [PATCH 25/39] ci: empty commit
From 5d84c3b52c8dfcb8640565dbde614fa1256483ae Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Sun, 12 Jan 2025 07:28:45 +0000
Subject: [PATCH 26/39] fix types
---
.../components/billing/estimatedTotal.svelte | 16 ++++
src/lib/sdk/billing.ts | 80 +++++++++++++++++++
2 files changed, 96 insertions(+)
create mode 100644 src/lib/components/billing/estimatedTotal.svelte
diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte
new file mode 100644
index 0000000000..40cac8a00a
--- /dev/null
+++ b/src/lib/components/billing/estimatedTotal.svelte
@@ -0,0 +1,16 @@
+
\ No newline at end of file
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index 85673c6156..04cbbaef6f 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -65,6 +65,28 @@ export type InvoiceList = {
total: number;
};
+export type Estimation = {
+ amount: number;
+ grossAmount: number;
+ credits: number;
+ discount: number;
+ items: EstimationItem[];
+}
+
+export type EstimationItem = {
+ label: string;
+ value: number;
+}
+
+export type EstimationDeleteOrganization = {
+ amount: number;
+ grossAmount: number;
+ credits: number;
+ discount: number;
+ items: EstimationItem[],
+ unpaidInvoices: Invoice[];
+}
+
export type Coupon = {
$id: string;
code: string;
@@ -396,6 +418,28 @@ export class Billing {
);
}
+ async estimationCreateOrganization(
+ billingPlan: string,
+ couponId: string = null,
+ invites: Array = [],
+ ): Promise {
+ const path = `/organizations`;
+ const params = {
+ billingPlan,
+ couponId,
+ invites,
+ };
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'POST',
+ uri,
+ {
+ 'content-type': 'application/json'
+ },
+ params
+ );
+ }
+
async deleteOrganization(organizationId: string): Promise {
const path = `/organizations/${organizationId}`;
const params = {
@@ -412,6 +456,18 @@ export class Billing {
);
}
+ async estimationDeleteOrganization(organizationId: string): Promise {
+ const path = `/organizations/${organizationId}/predictions/delete-organization`;
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'patch',
+ uri,
+ {
+ 'content-type': 'application/json'
+ }
+ );
+ }
+
async getOrganizationPlan(organizationId: string): Promise {
const path = `/organizations/${organizationId}/plan`;
const uri = new URL(this.client.config.endpoint + path);
@@ -475,6 +531,30 @@ export class Billing {
params
);
}
+
+ async estimationUpdatePlan(
+ organizationId: string,
+ billingPlan: string,
+ couponId: string = null,
+ invites: Array = [],
+ ): Promise {
+ const path = `/organizations/${organizationId}/predictions/update-plan`;
+ const params = {
+ billingPlan,
+ couponId,
+ invites,
+ };
+ const uri = new URL(this.client.config.endpoint + path);
+ return await this.client.call(
+ 'patch',
+ uri,
+ {
+ 'content-type': 'application/json'
+ },
+ params
+ );
+ }
+
async cancelDowngrade(
organizationId: string
): Promise {
From 31b1467a98ab23500f30063582bf1a91744fcb76 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Tue, 14 Jan 2025 08:05:18 +0000
Subject: [PATCH 27/39] use new estimation api for update plan and create
organiation
---
.../billing/discountsApplied.svelte | 21 +++++
.../components/billing/estimatedTotal.svelte | 93 +++++++++++++++++--
src/lib/sdk/billing.ts | 11 ++-
.../create-organization/+page.svelte | 12 +++
.../change-plan/+page.svelte | 16 +++-
5 files changed, 141 insertions(+), 12 deletions(-)
create mode 100644 src/lib/components/billing/discountsApplied.svelte
diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte
new file mode 100644
index 0000000000..0a815a88cc
--- /dev/null
+++ b/src/lib/components/billing/discountsApplied.svelte
@@ -0,0 +1,21 @@
+
+
+{#if value > 0}
+
+
+ -{formatCurrency(value)}
+
+{/if}
diff --git a/src/lib/components/billing/estimatedTotal.svelte b/src/lib/components/billing/estimatedTotal.svelte
index 40cac8a00a..f39f94f96e 100644
--- a/src/lib/components/billing/estimatedTotal.svelte
+++ b/src/lib/components/billing/estimatedTotal.svelte
@@ -1,16 +1,97 @@
+
+{#if estimation}
+
+
+
+ {#each estimation.items ?? [] as item}
+
+ {item.label}
+ {formatCurrency(item.value)}
+
+ {/each}
+ {#each estimation.discounts ?? [] as item}
+
+ {/each}
+
+
+
+ Total due
+
+
+ {formatCurrency(estimation.grossAmount)}
+
+
+
+
-
\ No newline at end of file
+
+
+{/if}
\ No newline at end of file
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index 7305e8abe1..f4734d500a 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -71,6 +71,9 @@ export type Estimation = {
credits: number;
discount: number;
items: EstimationItem[];
+ discounts: EstimationItem[];
+ trialDays: number;
+ trialEndDate: string | undefined;
}
export type EstimationItem = {
@@ -420,7 +423,7 @@ export class Billing {
couponId: string = null,
invites: Array = [],
): Promise {
- const path = `/organizations`;
+ const path = `/organizations/estimations/create-organization`;
const params = {
billingPlan,
couponId,
@@ -428,7 +431,7 @@ export class Billing {
};
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
- 'POST',
+ 'patch',
uri,
{
'content-type': 'application/json'
@@ -454,7 +457,7 @@ export class Billing {
}
async estimationDeleteOrganization(organizationId: string): Promise {
- const path = `/organizations/${organizationId}/predictions/delete-organization`;
+ const path = `/organizations/${organizationId}/estimations/delete-organization`;
const uri = new URL(this.client.config.endpoint + path);
return await this.client.call(
'patch',
@@ -535,7 +538,7 @@ export class Billing {
couponId: string = null,
invites: Array = [],
): Promise {
- const path = `/organizations/${organizationId}/predictions/update-plan`;
+ const path = `/organizations/${organizationId}/estimations/update-plan`;
const params = {
billingPlan,
couponId,
diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte
index 05da83c37f..59e84076cf 100644
--- a/src/routes/(console)/create-organization/+page.svelte
+++ b/src/routes/(console)/create-organization/+page.svelte
@@ -9,6 +9,7 @@
PlanSelection,
SelectPaymentMethod
} from '$lib/components/billing';
+ import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte';
import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte';
import Default from '$lib/components/roles/default.svelte';
import { BillingPlan, Dependencies } from '$lib/constants';
@@ -51,6 +52,7 @@
let billingPlan: BillingPlan = BillingPlan.FREE;
let paymentMethodId: string;
let collaborators: string[] = [];
+ let couponId: string | undefined;
let couponData: Partial = {
code: null,
status: null,
@@ -233,6 +235,11 @@
id="members" />
+
{#if !couponData?.code}
{#if billingPlan !== BillingPlan.FREE}
+
{/if}
{/if}
+
+
+
{#if isDowngrade}
{#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM}
-
+
{:else if $organization.billingPlan !== BillingPlan.CUSTOM}
{/if}
From d401ade41b53f9b2a763d1583896576385dac2e4 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 15 Jan 2025 03:30:33 +0000
Subject: [PATCH 28/39] fixes
---
src/lib/components/billing/discountsApplied.svelte | 6 +++++-
src/routes/(console)/apply-credit/+page.svelte | 10 +++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/src/lib/components/billing/discountsApplied.svelte b/src/lib/components/billing/discountsApplied.svelte
index 0a815a88cc..028854d277 100644
--- a/src/lib/components/billing/discountsApplied.svelte
+++ b/src/lib/components/billing/discountsApplied.svelte
@@ -16,6 +16,10 @@
- -{formatCurrency(value)}
+ {#if value >= 100}
+ Credits applied
+ {:else}
+ -{formatCurrency(value)}
+ {/if}
{/if}
diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte
index 884fd1763e..74d003861f 100644
--- a/src/routes/(console)/apply-credit/+page.svelte
+++ b/src/routes/(console)/apply-credit/+page.svelte
@@ -8,6 +8,7 @@
EstimatedTotalBox,
SelectPaymentMethod
} from '$lib/components/billing';
+ import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte';
import { BillingPlan, Dependencies } from '$lib/constants';
import { Button, Form, FormList, InputSelect, InputTags, InputText } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
@@ -285,12 +286,11 @@
{:else if selectedOrgId}
-
+ couponId={couponData.code}>
{#if campaign?.template === 'review' && (campaign?.cta || campaign?.claimed || campaign?.unclaimed)}
{campaign?.cta}
@@ -303,7 +303,7 @@
{/if}
-
+
{/if}
From 293eac04ff0a9bfa15228560d92f5d7e88c56edd Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 15 Jan 2025 06:50:01 +0000
Subject: [PATCH 29/39] refactor plan selection
---
src/lib/components/billing/index.ts | 2 +
src/lib/components/billing/selectPlan.svelte | 52 +++++++++++++++++++
src/lib/sdk/billing.ts | 6 ++-
.../create-organization/+page.svelte | 8 +--
.../change-plan/+page.svelte | 22 +++-----
5 files changed, 69 insertions(+), 21 deletions(-)
create mode 100644 src/lib/components/billing/selectPlan.svelte
diff --git a/src/lib/components/billing/index.ts b/src/lib/components/billing/index.ts
index 266d217d8a..0643e5922d 100644
--- a/src/lib/components/billing/index.ts
+++ b/src/lib/components/billing/index.ts
@@ -7,3 +7,5 @@ export { default as PlanComparisonBox } from './planComparisonBox.svelte';
export { default as EmptyCardCloud } from './emptyCardCloud.svelte';
export { default as CreditsApplied } from './creditsApplied.svelte';
export { default as PlanSelection } from './planSelection.svelte';
+export { default as EstimatedTotal } from './estimatedTotal.svelte';
+export { default as SelectPlan } from './selectPlan.svelte';
\ No newline at end of file
diff --git a/src/lib/components/billing/selectPlan.svelte b/src/lib/components/billing/selectPlan.svelte
new file mode 100644
index 0000000000..ecff50f99f
--- /dev/null
+++ b/src/lib/components/billing/selectPlan.svelte
@@ -0,0 +1,52 @@
+
+
+{#if billingPlan}
+
+ {#each $plansInfo.values() as plan}
+
+
+
+
+
+ {plan.name}
+ {#if $organization?.billingPlan === plan.$id && !isNewOrg}
+ Current plan
+ {/if}
+
+
+ {plan.desc}
+
+
+ {formatCurrency(plan?.price ?? 0)}
+
+
+
+
+
+ {/each}
+
+{/if}
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index f4734d500a..2245053c66 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -296,7 +296,9 @@ export type PlanAddon = {
export type Plan = {
$id: string;
name: string;
+ desc: string;
price: number;
+ order: number;
bandwidth: number;
storage: number;
webhooks: number;
@@ -332,7 +334,7 @@ export type Plan = {
supportsCredit: boolean;
};
-export type PlansInfo = {
+export type PlanList = {
plans: Plan[];
total: number;
};
@@ -1262,7 +1264,7 @@ export class Billing {
);
}
- async getPlansInfo(): Promise {
+ async getPlansInfo(): Promise {
const path = `/console/plans`;
const params = {};
const uri = new URL(this.client.config.endpoint + path);
diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte
index 59e84076cf..3b758b0d39 100644
--- a/src/routes/(console)/create-organization/+page.svelte
+++ b/src/routes/(console)/create-organization/+page.svelte
@@ -6,8 +6,10 @@
import {
EstimatedTotalBox,
PlanComparisonBox,
- PlanSelection,
- SelectPaymentMethod
+ SelectPaymentMethod,
+
+ SelectPlan
+
} from '$lib/components/billing';
import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte';
import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte';
@@ -222,7 +224,7 @@
For more details on our plans, visit our
pricing page .
-
+
{#if billingPlan !== BillingPlan.FREE}
$organization.billingPlan;
- $: isDowngrade = billingPlan < $organization.billingPlan;
+ $: isUpgrade = $plansInfo.get(billingPlan).order > $currentPlan.order;
+ $: isDowngrade = $plansInfo.get(billingPlan).order < $currentPlan.order;
$: if (billingPlan !== BillingPlan.FREE) {
loadPaymentMethods();
}
@@ -300,9 +299,8 @@
>Your contract is not eligible for manual changes. Please reach out to schedule
a call or setup a dialog.
{/if}
-
- {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM}
+ {#if billingPlan !== BillingPlan.FREE && $organization.billingPlan !== billingPlan && $organization.billingPlan !== BillingPlan.CUSTOM && isUpgrade}
-
+ {couponId} />
{:else if $organization.billingPlan !== BillingPlan.CUSTOM}
{/if}
From c5676817c3cfc63e2f8f001576aed2fb32bb1715 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 15 Jan 2025 07:31:04 +0000
Subject: [PATCH 30/39] fix after sync
---
src/lib/components/billing/estimatedTotalBox.svelte | 10 +++++-----
src/lib/components/billing/selectPlan.svelte | 1 -
src/routes/(console)/apply-credit/+page.svelte | 7 +------
src/routes/+layout.ts | 1 -
4 files changed, 6 insertions(+), 13 deletions(-)
diff --git a/src/lib/components/billing/estimatedTotalBox.svelte b/src/lib/components/billing/estimatedTotalBox.svelte
index 581e261b5f..4d96f87c4d 100644
--- a/src/lib/components/billing/estimatedTotalBox.svelte
+++ b/src/lib/components/billing/estimatedTotalBox.svelte
@@ -28,12 +28,12 @@
$: currentOrgPlan = $plansInfo.get(currentTier);
$: unUsedBalances = isScaleUpgrade
? currentOrgPlan.price +
- (collaborators?.length ?? 0) * (currentOrgPlan?.addons?.member?.price ?? 0)
+ (collaborators?.length ?? 0) * (currentOrgPlan?.addons?.seats?.price ?? 0)
: isScaleDowngrade
? currentOrgPlan.price
: 0;
- $: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0);
+ $: extraSeatsCost = (collaborators?.length ?? 0) * (selectedPlan?.addons?.seats?.price ?? 0);
$: grossCost = isScaleUpgrade
? selectedPlan.price + extraSeatsCost - unUsedBalances
: selectedPlan.price + extraSeatsCost;
@@ -59,7 +59,7 @@
{formatCurrency(
isScaleDowngrade
- ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.member?.price ?? 0)
+ ? (collaborators?.length ?? 0) * (selectedPlan?.addons?.seats?.price ?? 0)
: extraSeatsCost
)}
@@ -102,11 +102,11 @@
You'll pay {formatCurrency(estimatedTotal)} now, with your first
billing cycle starting on
{!currentPlan.trialDays
+ >{!currentOrgPlan.trialDays
? toLocaleDate(billingPayDate.toString())
: toLocaleDate(trialEndDate.toString())} . Once your credits run out, you'll be charged
- {formatCurrency(currentPlan.price)} plus usage fees every 30 days.
+ {formatCurrency(currentOrgPlan.price)} plus usage fees every 30 days.
diff --git a/src/lib/components/billing/selectPlan.svelte b/src/lib/components/billing/selectPlan.svelte
index ecff50f99f..4447c17e3f 100644
--- a/src/lib/components/billing/selectPlan.svelte
+++ b/src/lib/components/billing/selectPlan.svelte
@@ -8,7 +8,6 @@
export let billingPlan: string;
export let anyOrgFree = false;
export let isNewOrg = false;
- export let selfService = true;
let classes: string = '';
export { classes as class };
diff --git a/src/routes/(console)/apply-credit/+page.svelte b/src/routes/(console)/apply-credit/+page.svelte
index 502ede7ade..a33884a41d 100644
--- a/src/routes/(console)/apply-credit/+page.svelte
+++ b/src/routes/(console)/apply-credit/+page.svelte
@@ -3,12 +3,7 @@
import { base } from '$app/paths';
import { page } from '$app/stores';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
- import {
- CreditsApplied,
- EstimatedTotalBox,
- SelectPaymentMethod
- } from '$lib/components/billing';
- import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte';
+ import { CreditsApplied, EstimatedTotal, SelectPaymentMethod } from '$lib/components/billing';
import { BillingPlan, Dependencies } from '$lib/constants';
import { Button, Form, FormList, InputSelect, InputTags, InputText } from '$lib/elements/forms';
import { toLocaleDate } from '$lib/helpers/date';
diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts
index eb96a29c26..8161662735 100644
--- a/src/routes/+layout.ts
+++ b/src/routes/+layout.ts
@@ -6,7 +6,6 @@ import { redirect } from '@sveltejs/kit';
import { Dependencies } from '$lib/constants';
import type { LayoutLoad } from './$types';
import { redirectTo } from './store';
-import { isCloud } from '$lib/system';
import { base } from '$app/paths';
import type { Account } from '$lib/stores/user';
import type { AppwriteException } from '@appwrite.io/console';
From 8c9c413e4f0f4611c2730657adbdf490c7db8e09 Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 15 Jan 2025 07:54:29 +0000
Subject: [PATCH 31/39] fix coupon
---
.../create-organization/+page.svelte | 14 ----------
.../change-plan/+page.svelte | 27 +++++--------------
2 files changed, 7 insertions(+), 34 deletions(-)
diff --git a/src/routes/(console)/create-organization/+page.svelte b/src/routes/(console)/create-organization/+page.svelte
index 50ba69eff1..03ffc63d79 100644
--- a/src/routes/(console)/create-organization/+page.svelte
+++ b/src/routes/(console)/create-organization/+page.svelte
@@ -247,15 +247,6 @@
placeholder="Enter coupon code"
id="couponId" />
- {#if !couponData?.code}
- (showCreditModal = true)}>
- Add credits
-
- {/if}
{/if}
@@ -265,11 +256,6 @@
{collaborators}
{couponId}
/>
-
{:else}
{/if}
diff --git a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
index 7fd39a911b..f300a7bd0f 100644
--- a/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/change-plan/+page.svelte
@@ -4,10 +4,7 @@
import { page } from '$app/stores';
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
import { Alert } from '$lib/components';
- import {
- PlanComparisonBox,
- SelectPaymentMethod
- } from '$lib/components/billing';
+ import { PlanComparisonBox, SelectPaymentMethod } from '$lib/components/billing';
import EstimatedTotal from '$lib/components/billing/estimatedTotal.svelte';
import PlanExcess from '$lib/components/billing/planExcess.svelte';
import SelectPlan from '$lib/components/billing/selectPlan.svelte';
@@ -299,10 +296,7 @@
>Your contract is not eligible for manual changes. Please reach out to schedule
a call or setup a dialog.
{/if}
-
+
{#if isDowngrade}
{#if billingPlan === BillingPlan.FREE}
@@ -338,20 +332,13 @@
validityMessage="Invalid email address"
id="members" />
+
- {#if !couponData?.code}
- (showCreditModal = true)}>
- Add credits
-
- {/if}
{/if}
-
-
-
{#if isDowngrade}
Date: Wed, 15 Jan 2025 08:59:36 +0000
Subject: [PATCH 32/39] fix history not showing
---
.../organization-[organization]/billing/paymentHistory.svelte | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
index 8a50a4efc3..5ee85510ca 100644
--- a/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/paymentHistory.svelte
@@ -62,8 +62,7 @@
request();
}
-
-{#if $organization?.billingPlan === BillingPlan.FREE && invoiceList.total > 0}
+{#if $organization?.billingPlan !== BillingPlan.FREE && invoiceList.total > 0}
Payment history
From dee3b530debaabfebae519b517eff22894d2a7bb Mon Sep 17 00:00:00 2001
From: Damodar Lohani
Date: Wed, 15 Jan 2025 09:33:57 +0000
Subject: [PATCH 33/39] fix summary
---
src/lib/sdk/billing.ts | 4 +++-
.../billing/+page.svelte | 1 +
.../billing/planSummary.svelte | 18 ++++++++----------
3 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/src/lib/sdk/billing.ts b/src/lib/sdk/billing.ts
index d3078688c9..0d0824561d 100644
--- a/src/lib/sdk/billing.ts
+++ b/src/lib/sdk/billing.ts
@@ -171,10 +171,12 @@ export type Aggregation = {
* Total amount of the invoice.
*/
amount: number;
+ additionalMembers: number;
+
/**
* Price for additional members
*/
- additionalMembers: number;
+ additionalMemberAmount: number;
/**
* Total storage usage.
*/
diff --git a/src/routes/(console)/organization-[organization]/billing/+page.svelte b/src/routes/(console)/organization-[organization]/billing/+page.svelte
index 25b35dc327..cc0fb72d17 100644
--- a/src/routes/(console)/organization-[organization]/billing/+page.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/+page.svelte
@@ -123,6 +123,7 @@
creditList={data?.creditList}
members={data?.members}
currentPlan={data?.aggregationBillingPlan}
+ currentAggregation={data?.billingAggregation}
currentInvoice={data?.billingInvoice} />
diff --git a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
index a2b3f05ced..3d8a89c6d4 100644
--- a/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
+++ b/src/routes/(console)/organization-[organization]/billing/planSummary.svelte
@@ -5,7 +5,7 @@
import { toLocaleDate } from '$lib/helpers/date';
import { plansInfo, tierToPlan, upgradeURL } from '$lib/stores/billing';
import { organization } from '$lib/stores/organization';
- import type { CreditList, Invoice, Plan } from '$lib/sdk/billing';
+ import type { Aggregation, CreditList, Invoice, Plan } from '$lib/sdk/billing';
import { abbreviateNumber, formatCurrency, formatNumberWithCommas } from '$lib/helpers/numbers';
import { humanFileSize } from '$lib/helpers/sizeConvertion';
import { BillingPlan } from '$lib/constants';
@@ -18,17 +18,16 @@
export let currentPlan: Plan;
export let creditList: CreditList;
export let currentInvoice: Invoice | undefined = undefined;
+ export let currentAggregation: Aggregation | undefined = undefined
let showCancel: boolean = false;
- const extraMembers = members.total > 1 ? members.total - 1 : 0;
const availableCredit = creditList.available;
const today = new Date();
const isTrial =
new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 &&
$plansInfo.get($organization.billingPlan)?.trialDays;
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
- const extraAddons = currentInvoice ? currentInvoice.usage?.length : 0;
{#if $organization}
@@ -64,7 +63,7 @@
Add-ons {extraMembers ? extraAddons + 1 : extraAddons}
+ >{currentAggregation.additionalMembers > 0 ? currentInvoice.usage.length + 1 : currentInvoice.usage.length}
@@ -78,7 +77,7 @@