mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
Update console URL from pkg.pr.new to try-module.cloud and migrate billing API calls
This commit is contained in:
+1
-1
@@ -22,7 +22,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@ai-sdk/svelte": "^1.1.24",
|
||||
"@appwrite.io/console": "https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959",
|
||||
"@appwrite.io/console": "https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7",
|
||||
"@appwrite.io/pink": "0.25.0",
|
||||
"@appwrite.io/pink-icons": "0.25.0",
|
||||
"@appwrite.io/pink-icons-svelte": "^2.0.0-RC.1",
|
||||
|
||||
Generated
+5
-5
@@ -12,8 +12,8 @@ importers:
|
||||
specifier: ^1.1.24
|
||||
version: 1.1.24(svelte@5.25.3)(zod@3.24.3)
|
||||
'@appwrite.io/console':
|
||||
specifier: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959
|
||||
version: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959
|
||||
specifier: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7
|
||||
version: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7
|
||||
'@appwrite.io/pink':
|
||||
specifier: 0.25.0
|
||||
version: 0.25.0
|
||||
@@ -254,8 +254,8 @@ packages:
|
||||
'@analytics/type-utils@0.6.2':
|
||||
resolution: {integrity: sha512-TD+xbmsBLyYy/IxFimW/YL/9L2IEnM7/EoV9Aeh56U64Ify8o27HJcKjo38XY9Tcn0uOq1AX3thkKgvtWvwFQg==}
|
||||
|
||||
'@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959':
|
||||
resolution: {tarball: https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959}
|
||||
'@appwrite.io/console@https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7':
|
||||
resolution: {tarball: https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7}
|
||||
version: 1.5.2
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@2.0.0-RC.1':
|
||||
@@ -3615,7 +3615,7 @@ snapshots:
|
||||
|
||||
'@analytics/type-utils@0.6.2': {}
|
||||
|
||||
'@appwrite.io/console@https://pkg.pr.new/appwrite-labs/cloud/@appwrite.io/console@1959': {}
|
||||
'@appwrite.io/console@https://try-module.cloud/module/@appwrite/%40appwrite.io%2Fconsole@e50c8d0b7': {}
|
||||
|
||||
'@appwrite.io/pink-icons-svelte@2.0.0-RC.1(svelte@5.25.3)':
|
||||
dependencies:
|
||||
|
||||
@@ -7,7 +7,7 @@ import { isCloud } from '$lib/system';
|
||||
export const orgSearcher = (async (query: string) => {
|
||||
const { teams } = !isCloud
|
||||
? await sdk.forConsole.teams.list()
|
||||
: await sdk.forConsole.billing.listOrganization();
|
||||
: await sdk.forConsole.organizations.list();
|
||||
|
||||
return teams
|
||||
.filter((organization) => organization.name.toLowerCase().includes(query.toLowerCase()))
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
import { confirmSetup } from '$lib/stores/stripe';
|
||||
|
||||
async function verifyPaymentMethod() {
|
||||
const method = await sdk.forConsole.billing.setupPaymentMandate(
|
||||
$organization.$id,
|
||||
const method = await sdk.forConsole.account.updatePaymentMethodMandateOptions(
|
||||
$paymentMissingMandate.$id
|
||||
);
|
||||
await confirmSetup(method.clientSecret, method.$id);
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
|
||||
async function addCoupon() {
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
|
||||
const response = await sdk.forConsole.account.getCoupon(coupon);
|
||||
couponData = response;
|
||||
dispatch('validation', couponData);
|
||||
coupon = null;
|
||||
|
||||
@@ -2,15 +2,16 @@
|
||||
import { InputChoice, InputNumber } from '$lib/elements/forms';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import { formatCurrency } from '$lib/helpers/numbers';
|
||||
import type { Coupon, PlansMap } from '$lib/sdk/billing';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { type Tier } from '$lib/stores/billing';
|
||||
import { Card, Divider, Layout, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { CreditsApplied } from '.';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export let billingPlan: Tier;
|
||||
export let collaborators: string[];
|
||||
export let couponData: Partial<Coupon>;
|
||||
export let plans: PlansMap;
|
||||
export let plans: Map<Tier, Models.BillingPlan>;
|
||||
export let billingBudget: number;
|
||||
export let fixedCoupon = false; // If true, the coupon cannot be removed
|
||||
export let isDowngrade = false;
|
||||
@@ -29,9 +30,7 @@
|
||||
? grossCost - couponData.credits
|
||||
: 0
|
||||
: grossCost;
|
||||
$: trialEndDate = new Date(
|
||||
billingPayDate.getTime() + currentPlan.trialDays * 24 * 60 * 60 * 1000
|
||||
);
|
||||
$: trialEndDate = new Date(billingPayDate.getTime() + currentPlan.trial * 24 * 60 * 60 * 1000);
|
||||
</script>
|
||||
|
||||
<Card.Base padding="s">
|
||||
@@ -54,7 +53,7 @@
|
||||
<Layout.Stack direction="row" justifyContent="space-between">
|
||||
<Typography.Text>
|
||||
Upcoming charge<br />
|
||||
Due on {!currentPlan.trialDays
|
||||
Due on {!currentPlan.trial
|
||||
? toLocaleDate(billingPayDate.toString())
|
||||
: toLocaleDate(trialEndDate.toString())}</Typography.Text>
|
||||
<Typography.Text>{formatCurrency(estimatedTotal)}</Typography.Text>
|
||||
@@ -64,7 +63,7 @@
|
||||
You'll pay <b>{formatCurrency(estimatedTotal)}</b> now, with your first billing cycle
|
||||
starting on
|
||||
<b
|
||||
>{!currentPlan.trialDays
|
||||
>{!currentPlan.trial
|
||||
? toLocaleDate(billingPayDate.toString())
|
||||
: toLocaleDate(trialEndDate.toString())}</b
|
||||
>. {#if couponData?.status === 'active'}Once your credits run out, you'll be charged
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { formatNum } from '$lib/helpers/string';
|
||||
import { plansInfo, tierFree, tierPro, tierScale, type Tier } from '$lib/stores/billing';
|
||||
import { plansInfo, tierFree, tierPro, tierScale } from '$lib/stores/billing';
|
||||
import { Card, Layout, Tabs, Typography } from '@appwrite.io/pink-svelte';
|
||||
|
||||
export let downgrade = false;
|
||||
|
||||
let selectedTab: Tier = BillingPlan.FREE;
|
||||
let selectedTab: BillingPlan = BillingPlan.FREE;
|
||||
|
||||
$: plan = $plansInfo.get(selectedTab);
|
||||
</script>
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { calculateExcess, plansInfo, tierToPlan, type Tier } from '$lib/stores/billing';
|
||||
import { calculateExcess, plansInfo, tierToPlan } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import { humanFileSize } from '$lib/helpers/sizeConvertion';
|
||||
import { abbreviateNumber } from '$lib/helpers/numbers';
|
||||
import { formatNum } from '$lib/helpers/string';
|
||||
import { onMount } from 'svelte';
|
||||
import type { Aggregation } from '$lib/sdk/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { Alert, Icon, Table, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export let tier: Tier;
|
||||
export let tier: BillingPlan;
|
||||
|
||||
const plan = $plansInfo?.get(tier);
|
||||
let excess: {
|
||||
@@ -22,11 +22,11 @@
|
||||
executions?: number;
|
||||
members?: number;
|
||||
} = null;
|
||||
let aggregation: Aggregation = null;
|
||||
let aggregation: Models.AggregationTeam = null;
|
||||
let showExcess = false;
|
||||
|
||||
onMount(async () => {
|
||||
aggregation = await sdk.forConsole.billing.getAggregation(
|
||||
aggregation = await sdk.forConsole.organizations.getAggregation(
|
||||
$organization.$id,
|
||||
$organization.billingAggregationId
|
||||
);
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
async function addCoupon() {
|
||||
try {
|
||||
// const response = await sdk.forConsole.billing.getCoupon(coupon);
|
||||
const response = await sdk.forConsole.billing.getCouponAccount(coupon); //TODO: double check that this is the correct method
|
||||
const response = await sdk.forConsole.account.getCoupon(coupon);
|
||||
|
||||
if (response.onlyNewOrgs && !isNewOrg) {
|
||||
show = false;
|
||||
|
||||
@@ -521,6 +521,9 @@ export const eventServices: Array<EventService> = [
|
||||
];
|
||||
|
||||
export enum BillingPlan {
|
||||
Tier0 = 'tier-0',
|
||||
Tier1 = 'tier-1',
|
||||
Tier2 = 'tier-2',
|
||||
FREE = 'tier-0',
|
||||
PRO = 'tier-1',
|
||||
SCALE = 'tier-2',
|
||||
|
||||
@@ -5,22 +5,20 @@
|
||||
import AppwriteLogoLight from '$lib/images/appwrite-logo-light.svg';
|
||||
import LoginDark from '$lib/images/login/login-dark-mode.png';
|
||||
import LoginLight from '$lib/images/login/login-light-mode.png';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { app } from '$lib/stores/app';
|
||||
import type { Campaign } from '$lib/stores/campaigns';
|
||||
import { Typography, Layout, Avatar } from '@appwrite.io/pink-svelte';
|
||||
import { getCampaignImageUrl } from '$routes/(public)/card/helpers';
|
||||
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
export const imgLight = LoginLight;
|
||||
export const imgDark = LoginDark;
|
||||
|
||||
export let campaign: Campaign = null;
|
||||
export let coupon: Coupon = null;
|
||||
export let campaign: Models.Campaign = null;
|
||||
export let coupon: Models.Coupon = null;
|
||||
export let align: 'start' | 'center' | 'end' = 'start';
|
||||
|
||||
$: variation = ((coupon?.campaign ?? campaign) ? campaign?.template : 'default') as
|
||||
| 'default'
|
||||
| Campaign['template'];
|
||||
| Models.Campaign['template'];
|
||||
|
||||
let currentReviewNumber = 0;
|
||||
$: currentReview = campaign?.reviews?.[currentReviewNumber];
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { Campaign } from '$lib/stores/campaigns';
|
||||
import type { Client, Models } from '@appwrite.io/console';
|
||||
import type { PaymentMethod } from '@stripe/stripe-js';
|
||||
import type { Organization, OrganizationError, OrganizationList } from '../stores/organization';
|
||||
import type { BillingPlan } from '$lib/constants';
|
||||
|
||||
export type PaymentMethodData = {
|
||||
$id: string;
|
||||
@@ -345,7 +346,7 @@ export type PlanList = {
|
||||
total: number;
|
||||
};
|
||||
|
||||
export type PlansMap = Map<Tier, Plan>;
|
||||
export type PlansMap = Map<BillingPlan, Models.BillingPlan>;
|
||||
|
||||
export type Roles = {
|
||||
scopes: string[];
|
||||
@@ -375,7 +376,10 @@ export class Billing {
|
||||
);
|
||||
}
|
||||
|
||||
async validateOrganization(organizationId: string, invites: string[]): Promise<Organization> {
|
||||
async validateOrganization(
|
||||
organizationId: string,
|
||||
invites: string[]
|
||||
): Promise<Models.Organization<Record<string, unknown>>> {
|
||||
const path = `/organizations/${organizationId}/validate`;
|
||||
const params = {
|
||||
organizationId,
|
||||
|
||||
+53
-50
@@ -12,19 +12,10 @@ import PaymentMandate from '$lib/components/billing/alerts/paymentMandate.svelte
|
||||
import { BillingPlan, NEW_DEV_PRO_UPGRADE_COUPON } from '$lib/constants';
|
||||
import { cachedStore } from '$lib/helpers/cache';
|
||||
import { sizeToBytes, type Size } from '$lib/helpers/sizeConvertion';
|
||||
import type {
|
||||
AddressesList,
|
||||
Aggregation,
|
||||
Invoice,
|
||||
InvoiceList,
|
||||
PaymentList,
|
||||
PaymentMethodData,
|
||||
Plan,
|
||||
PlansMap
|
||||
} from '$lib/sdk/billing';
|
||||
import type { AddressesList, PaymentList, PaymentMethodData, PlansMap } from '$lib/sdk/billing';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { activeHeaderAlert, orgMissingPaymentMethod } from '$routes/(console)/store';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import { derived, get, writable } from 'svelte/store';
|
||||
import { headerAlert } from './headerAlert';
|
||||
import { addNotification, notifications } from './notifications';
|
||||
@@ -78,13 +69,13 @@ export function getRoleLabel(role: string) {
|
||||
return roles.find((r) => r.value === role)?.label ?? role;
|
||||
}
|
||||
|
||||
export function tierToPlan(tier: Tier) {
|
||||
export function tierToPlan(tier: string) {
|
||||
switch (tier) {
|
||||
case BillingPlan.FREE:
|
||||
case BillingPlan.Tier0:
|
||||
return tierFree;
|
||||
case BillingPlan.PRO:
|
||||
case BillingPlan.Tier1:
|
||||
return tierPro;
|
||||
case BillingPlan.SCALE:
|
||||
case BillingPlan.Tier2:
|
||||
return tierScale;
|
||||
case BillingPlan.GITHUB_EDUCATION:
|
||||
return tierGitHubEducation;
|
||||
@@ -99,23 +90,23 @@ export function tierToPlan(tier: Tier) {
|
||||
|
||||
export function getNextTier(tier: Tier) {
|
||||
switch (tier) {
|
||||
case BillingPlan.FREE:
|
||||
return BillingPlan.PRO;
|
||||
case BillingPlan.PRO:
|
||||
return BillingPlan.SCALE;
|
||||
case BillingPlan.Tier0:
|
||||
return BillingPlan.Tier1;
|
||||
case BillingPlan.Tier1:
|
||||
return BillingPlan.Tier2;
|
||||
default:
|
||||
return BillingPlan.PRO;
|
||||
return BillingPlan.Tier1;
|
||||
}
|
||||
}
|
||||
|
||||
export function getPreviousTier(tier: Tier) {
|
||||
switch (tier) {
|
||||
case BillingPlan.PRO:
|
||||
return BillingPlan.FREE;
|
||||
case BillingPlan.SCALE:
|
||||
return BillingPlan.PRO;
|
||||
case BillingPlan.Tier1:
|
||||
return BillingPlan.Tier0;
|
||||
case BillingPlan.Tier2:
|
||||
return BillingPlan.Tier1;
|
||||
default:
|
||||
return BillingPlan.FREE;
|
||||
return BillingPlan.Tier0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,12 +135,16 @@ export type PlanServices =
|
||||
| 'authPhone'
|
||||
| 'imageTransformations';
|
||||
|
||||
export function getServiceLimit(serviceId: PlanServices, tier: Tier = null, plan?: Plan): number {
|
||||
export function getServiceLimit(
|
||||
serviceId: PlanServices,
|
||||
tier: BillingPlan = null,
|
||||
plan?: Models.BillingPlan
|
||||
): number {
|
||||
if (!isCloud) return 0;
|
||||
if (!serviceId) return 0;
|
||||
const info = get(plansInfo);
|
||||
if (!info) return 0;
|
||||
plan ??= info.get(tier ?? get(organization)?.billingPlan);
|
||||
plan ??= info.get(tier ?? (get(organization)?.billingPlan as unknown as BillingPlan));
|
||||
// members are no longer a variable on plan itself!
|
||||
// the correct info for members/seats, resides in `addons`.
|
||||
// plan > addons > seats/others
|
||||
@@ -162,7 +157,7 @@ export function getServiceLimit(serviceId: PlanServices, tier: Tier = null, plan
|
||||
}
|
||||
|
||||
export const failedInvoice = cachedStore<
|
||||
Invoice,
|
||||
Models.Invoice,
|
||||
{
|
||||
load: (orgId: string) => Promise<void>;
|
||||
}
|
||||
@@ -171,7 +166,7 @@ export const failedInvoice = cachedStore<
|
||||
load: async (orgId) => {
|
||||
if (!isCloud) set(null);
|
||||
if (!get(canSeeBilling)) set(null);
|
||||
const failedInvoices = await sdk.forConsole.billing.listInvoices(orgId, [
|
||||
const failedInvoices = await sdk.forConsole.organizations.listInvoices(orgId, [
|
||||
Query.equal('status', 'failed')
|
||||
]);
|
||||
// const failedInvoices = invoices.invoices;
|
||||
@@ -188,7 +183,7 @@ export const failedInvoice = cachedStore<
|
||||
};
|
||||
});
|
||||
|
||||
export const actionRequiredInvoices = writable<InvoiceList>(null);
|
||||
export const actionRequiredInvoices = writable<Models.InvoiceList>(null);
|
||||
|
||||
export type TierData = {
|
||||
name: string;
|
||||
@@ -229,7 +224,7 @@ export const tierEnterprise: TierData = {
|
||||
export const showUsageRatesModal = writable<boolean>(false);
|
||||
|
||||
export function checkForUsageFees(plan: Tier, id: PlanServices) {
|
||||
if (plan === BillingPlan.PRO || plan === BillingPlan.SCALE) {
|
||||
if (plan === BillingPlan.Tier2 || plan === BillingPlan.Tier1) {
|
||||
switch (id) {
|
||||
case 'bandwidth':
|
||||
case 'storage':
|
||||
@@ -260,7 +255,7 @@ export function checkForProjectLimitation(id: PlanServices) {
|
||||
}
|
||||
}
|
||||
|
||||
export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: number) {
|
||||
export function isServiceLimited(serviceId: PlanServices, plan: BillingPlan, total: number) {
|
||||
if (!total) return false;
|
||||
const limit = getServiceLimit(serviceId) || Infinity;
|
||||
const isLimited = limit !== 0 && limit < Infinity;
|
||||
@@ -269,7 +264,7 @@ export function isServiceLimited(serviceId: PlanServices, plan: Tier, total: num
|
||||
}
|
||||
|
||||
export function calculateTrialDay(org: Organization) {
|
||||
if (org?.billingPlan === BillingPlan.FREE) return false;
|
||||
if (org?.billingPlan === BillingPlan.Tier0) return false;
|
||||
const endDate = new Date(org?.billingStartDate);
|
||||
const today = new Date();
|
||||
|
||||
@@ -297,7 +292,7 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
readOnly.set(false);
|
||||
return;
|
||||
}
|
||||
if (org?.billingPlan !== BillingPlan.FREE) {
|
||||
if (org?.billingPlan !== BillingPlan.Tier0) {
|
||||
const { budgetLimit } = org?.billingLimits ?? {};
|
||||
|
||||
if (budgetLimit && budgetLimit >= 100) {
|
||||
@@ -323,7 +318,7 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
];
|
||||
|
||||
const members = org.total;
|
||||
const plan = get(plansInfo)?.get(org.billingPlan);
|
||||
const plan = get(plansInfo)?.get(org.billingPlan as BillingPlan);
|
||||
const membersOverflow =
|
||||
members > plan.addons.seats.limit ? members - (plan.addons.seats.limit || members) : 0;
|
||||
|
||||
@@ -342,9 +337,9 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
if (now - lastNotification < 1000 * 60 * 60 * 24) return;
|
||||
|
||||
localStorage.setItem('limitReachedNotification', now.toString());
|
||||
let message = `<b>${org.name}</b> has reached <b>75%</b> of the ${tierToPlan(BillingPlan.FREE).name} plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
|
||||
let message = `<b>${org.name}</b> has reached <b>75%</b> of the ${tierToPlan(BillingPlan.Tier0).name} plan's ${resources.find((r) => r.value >= 75).name} limit. Upgrade to ensure there are no service disruptions.`;
|
||||
if (resources.filter((r) => r.value >= 75)?.length > 1) {
|
||||
message = `Usage for <b>${org.name}</b> has reached 75% of the ${tierToPlan(BillingPlan.FREE).name} plan limit. Upgrade to ensure there are no service disruptions.`;
|
||||
message = `Usage for <b>${org.name}</b> has reached 75% of the ${tierToPlan(BillingPlan.Tier0).name} plan limit. Upgrade to ensure there are no service disruptions.`;
|
||||
}
|
||||
addNotification({
|
||||
type: 'warning',
|
||||
@@ -376,9 +371,9 @@ export async function checkForUsageLimit(org: Organization) {
|
||||
}
|
||||
|
||||
export async function checkPaymentAuthorizationRequired(org: Organization) {
|
||||
if (org.billingPlan === BillingPlan.FREE) return;
|
||||
if (org.billingPlan === BillingPlan.Tier0) return;
|
||||
|
||||
const invoices = await sdk.forConsole.billing.listInvoices(org.$id, [
|
||||
const invoices = await sdk.forConsole.organizations.listInvoices(org.$id, [
|
||||
Query.equal('status', 'requires_authentication')
|
||||
]);
|
||||
|
||||
@@ -397,7 +392,7 @@ export async function checkPaymentAuthorizationRequired(org: Organization) {
|
||||
|
||||
export async function paymentExpired(org: Organization) {
|
||||
if (!org?.paymentMethodId) return;
|
||||
const payment = await sdk.forConsole.billing.getOrganizationPaymentMethod(
|
||||
const payment = await sdk.forConsole.organizations.getPaymentMethod(
|
||||
org.$id,
|
||||
org.paymentMethodId
|
||||
);
|
||||
@@ -460,7 +455,7 @@ export const paymentMissingMandate = writable<PaymentMethodData>(null);
|
||||
export async function checkForMandate(org: Organization) {
|
||||
const paymentId = org.paymentMethodId ?? org.backupPaymentMethodId;
|
||||
if (!paymentId) return;
|
||||
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentId);
|
||||
const paymentMethod = await sdk.forConsole.account.getPaymentMethod(paymentId);
|
||||
if (paymentMethod?.mandateId === null && paymentMethod?.country.toLowerCase() === 'in') {
|
||||
headerAlert.add({
|
||||
id: 'paymentMandate',
|
||||
@@ -474,8 +469,8 @@ export async function checkForMandate(org: Organization) {
|
||||
}
|
||||
|
||||
export async function checkForMissingPaymentMethod() {
|
||||
const orgs = await sdk.forConsole.billing.listOrganization([
|
||||
Query.notEqual('billingPlan', BillingPlan.FREE),
|
||||
const orgs = await sdk.forConsole.organizations.list([
|
||||
Query.notEqual('billingPlan', BillingPlan.Tier0),
|
||||
Query.isNull('paymentMethodId'),
|
||||
Query.isNull('backupPaymentMethodId')
|
||||
]);
|
||||
@@ -492,10 +487,10 @@ export async function checkForMissingPaymentMethod() {
|
||||
|
||||
// Display upgrade banner for new users after 1 week for 30 days
|
||||
export async function checkForNewDevUpgradePro(org: Organization) {
|
||||
if (org?.billingPlan !== BillingPlan.FREE || !browser) return;
|
||||
if (org?.billingPlan !== BillingPlan.Tier0 || !browser) return;
|
||||
|
||||
const orgs = await sdk.forConsole.billing.listOrganization([
|
||||
Query.notEqual('billingPlan', BillingPlan.FREE)
|
||||
const orgs = await sdk.forConsole.organizations.list([
|
||||
Query.notEqual('billingPlan', BillingPlan.Tier0)
|
||||
]);
|
||||
if (orgs?.total) return;
|
||||
|
||||
@@ -507,7 +502,7 @@ export async function checkForNewDevUpgradePro(org: Organization) {
|
||||
if (isDismissed) return;
|
||||
// check if coupon already applied
|
||||
try {
|
||||
await sdk.forConsole.billing.getCouponAccount(NEW_DEV_PRO_UPGRADE_COUPON);
|
||||
await sdk.forConsole.account.getCoupon(NEW_DEV_PRO_UPGRADE_COUPON);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
@@ -529,7 +524,7 @@ export const billingURL = derived(
|
||||
|
||||
export const hideBillingHeaderRoutes = ['/console/create-organization', '/console/account'];
|
||||
|
||||
export function calculateExcess(addon: Aggregation, plan: Plan) {
|
||||
export function calculateExcess(addon: Models.AggregationTeam, plan: Models.BillingPlan) {
|
||||
return {
|
||||
bandwidth: calculateResourceSurplus(addon.usageBandwidth, plan.bandwidth),
|
||||
storage: calculateResourceSurplus(addon.usageStorage, plan.storage, 'GB'),
|
||||
@@ -544,6 +539,14 @@ export function calculateResourceSurplus(total: number, limit: number, limitUnit
|
||||
return total > realLimit ? total - realLimit : 0;
|
||||
}
|
||||
|
||||
export function isOrganization(org: Organization | OrganizationError): org is Organization {
|
||||
return (org as Organization).$id !== undefined;
|
||||
export function isOrganization(
|
||||
org: Models.Organization<Record<string, unknown>> | OrganizationError
|
||||
): org is Models.Organization<Record<string, unknown>> {
|
||||
return '$id' in org && org.$id !== undefined;
|
||||
}
|
||||
|
||||
export function isOrganizationError(
|
||||
org: Models.Organization<Record<string, unknown>> | OrganizationError
|
||||
): org is OrganizationError {
|
||||
return !('$id' in org);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { BillingPlan } from '$lib/constants';
|
||||
import type { BillingPlan } from '@appwrite.io/console';
|
||||
|
||||
export type Campaign = {
|
||||
$id: string;
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import type { Tier } from './billing';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import type { BillingPlan } from '$lib/constants';
|
||||
|
||||
export type OrganizationError = {
|
||||
status: number;
|
||||
@@ -13,27 +12,8 @@ export type OrganizationError = {
|
||||
type: string;
|
||||
};
|
||||
|
||||
export type Organization = Models.Team<Record<string, unknown>> & {
|
||||
billingBudget: number;
|
||||
billingPlan: Tier;
|
||||
budgetAlerts: number[];
|
||||
paymentMethodId: string;
|
||||
backupPaymentMethodId: string;
|
||||
markedForDeletion: boolean;
|
||||
billingLimits: BillingLimits;
|
||||
billingCurrentInvoiceDate: string;
|
||||
billingNextInvoiceDate: string;
|
||||
billingTrialStartDate?: string;
|
||||
billingStartDate?: string;
|
||||
billingTrialDays?: number;
|
||||
billingAddressId?: string;
|
||||
amount: number;
|
||||
billingTaxId?: string;
|
||||
billingPlanDowngrade?: Tier;
|
||||
billingAggregationId: string;
|
||||
billingInvoiceId: string;
|
||||
status: string;
|
||||
remarks: string;
|
||||
export type Organization = Omit<Models.Organization<Record<string, unknown>>, 'billingPlan'> & {
|
||||
billingPlan: BillingPlan;
|
||||
};
|
||||
|
||||
export type OrganizationList = {
|
||||
@@ -54,11 +34,11 @@ export const newOrgModal = writable<boolean>(false);
|
||||
export const newMemberModal = writable<boolean>(false);
|
||||
export const organizationList = derived(
|
||||
page,
|
||||
($page) => $page.data.organizations as Models.TeamList<Record<string, unknown>>
|
||||
($page) => $page.data.organizations as Models.OrganizationList<Record<string, unknown>>
|
||||
);
|
||||
|
||||
export const organization = derived(page, ($page) => $page.data?.organization as Organization);
|
||||
export const currentPlan = derived(page, ($page) => $page.data?.currentPlan as Plan);
|
||||
export const currentPlan = derived(page, ($page) => $page.data?.currentPlan as Models.BillingPlan);
|
||||
export const members = derived(page, ($page) => $page.data.members as Models.MembershipList);
|
||||
|
||||
export const regions = writable<Models.ConsoleRegionList | undefined>(undefined);
|
||||
|
||||
@@ -20,7 +20,8 @@ import {
|
||||
Users,
|
||||
Vcs,
|
||||
Sites,
|
||||
Tokens
|
||||
Tokens,
|
||||
Organizations
|
||||
} from '@appwrite.io/console';
|
||||
import { Billing } from '../sdk/billing';
|
||||
import { Backups } from '../sdk/backups';
|
||||
@@ -121,6 +122,7 @@ export const sdk = {
|
||||
teams: new Teams(clientConsole),
|
||||
users: new Users(clientConsole),
|
||||
migrations: new Migrations(clientConsole),
|
||||
organizations: new Organizations(clientConsole),
|
||||
console: new Console(clientConsole),
|
||||
assistant: new Assistant(clientConsole),
|
||||
billing: new Billing(clientConsole),
|
||||
|
||||
@@ -21,7 +21,7 @@ export async function initializeStripe(node: HTMLElement) {
|
||||
if (!get(stripe)) return;
|
||||
isStripeInitialized.set(true);
|
||||
|
||||
const methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
const methods = await sdk.forConsole.account.listPaymentMethods();
|
||||
|
||||
// Get the client secret from empty payment method if available
|
||||
clientSecret = methods.paymentMethods?.filter(
|
||||
@@ -30,7 +30,7 @@ export async function initializeStripe(node: HTMLElement) {
|
||||
|
||||
// If there is no payment method, create an empty one and get the client secret
|
||||
if (!clientSecret) {
|
||||
paymentMethod = await sdk.forConsole.billing.createPaymentMethod();
|
||||
paymentMethod = await sdk.forConsole.account.createPaymentMethod();
|
||||
clientSecret = paymentMethod.clientSecret;
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ export async function submitStripeCard(name: string, organizationId?: string) {
|
||||
try {
|
||||
// If a payment method was created during initialization, use it, otherwise create a new one
|
||||
if (!paymentMethod) {
|
||||
paymentMethod = await sdk.forConsole.billing.createPaymentMethod();
|
||||
paymentMethod = await sdk.forConsole.account.createPaymentMethod();
|
||||
clientSecret = paymentMethod.clientSecret;
|
||||
}
|
||||
|
||||
@@ -94,9 +94,9 @@ export async function submitStripeCard(name: string, organizationId?: string) {
|
||||
}
|
||||
|
||||
if (setupIntent && setupIntent.status === 'succeeded') {
|
||||
const method = await sdk.forConsole.billing.setPaymentMethod(
|
||||
const method = await sdk.forConsole.account.updatePaymentMethodProvider(
|
||||
paymentMethod.$id,
|
||||
setupIntent.payment_method,
|
||||
setupIntent.payment_method.toString(),
|
||||
name
|
||||
);
|
||||
paymentElement.destroy();
|
||||
@@ -124,7 +124,7 @@ export async function confirmPayment(
|
||||
const url =
|
||||
window.location.origin + (route ? route : `${base}/organization-${orgId}/billing`);
|
||||
|
||||
const paymentMethod = await sdk.forConsole.billing.getPaymentMethod(paymentMethodId);
|
||||
const paymentMethod = await sdk.forConsole.account.getPaymentMethod(paymentMethodId);
|
||||
|
||||
const { error } = await get(stripe).confirmPayment({
|
||||
clientSecret: clientSecret,
|
||||
|
||||
@@ -310,7 +310,7 @@
|
||||
await checkPaymentAuthorizationRequired(org);
|
||||
await checkForMandate(org);
|
||||
|
||||
if ($plansInfo.get(org.billingPlan)?.trialDays) {
|
||||
if ($plansInfo.get(org.billingPlan)?.trial) {
|
||||
calculateTrialDay(org);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import type { Tier } from '$lib/stores/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, fetch, depends, parent }) => {
|
||||
await parent();
|
||||
@@ -25,18 +24,18 @@ export const load: LayoutLoad = async ({ params, fetch, depends, parent }) => {
|
||||
|
||||
const [data, variables] = await Promise.all([versionPromise, variablesPromise]);
|
||||
|
||||
let plansInfo = new Map<Tier, Plan>();
|
||||
let plansInfo = new Map<Tier, Models.BillingPlan>();
|
||||
if (isCloud) {
|
||||
const plansArray = await sdk.forConsole.billing.getPlansInfo();
|
||||
const plansArray = await sdk.forConsole.console.plans();
|
||||
plansInfo = plansArray.plans.reduce((map, plan) => {
|
||||
map.set(plan.$id as Tier, plan);
|
||||
return map;
|
||||
}, new Map<Tier, Plan>());
|
||||
}, new Map<Tier, Models.BillingPlan>());
|
||||
}
|
||||
|
||||
const organizations = !isCloud
|
||||
? await sdk.forConsole.teams.list()
|
||||
: await sdk.forConsole.billing.listOrganization();
|
||||
: await sdk.forConsole.organizations.list();
|
||||
|
||||
let projects = [];
|
||||
let currentOrgId = params.organization ? params.organization : prefs.organization;
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
>You are limited to 1 free organization per account</span>
|
||||
</Tooltip>
|
||||
{/if}
|
||||
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.FREE && $plansInfo.get(organization.billingPlan)?.trialDays}
|
||||
{#if organization?.billingTrialStartDate && $daysLeftInTrial > 0 && organization.billingPlan !== BillingPlan.FREE && $plansInfo.get(organization.billingPlan)?.trial}
|
||||
<Tooltip>
|
||||
<div class="u-flex u-cross-center">
|
||||
<Pill class="eyebrow-heading-3">TRIAL</Pill>
|
||||
|
||||
@@ -14,7 +14,7 @@ export const load: PageLoad = async ({ url, route }) => {
|
||||
|
||||
const organizations = !isCloud
|
||||
? await sdk.forConsole.teams.list(queries)
|
||||
: await sdk.forConsole.billing.listOrganization(queries);
|
||||
: await sdk.forConsole.organizations.list(queries);
|
||||
|
||||
return {
|
||||
offset,
|
||||
|
||||
@@ -7,8 +7,8 @@ export const load: PageLoad = async ({ depends }) => {
|
||||
depends(Dependencies.ADDRESS);
|
||||
|
||||
const [paymentMethods, addressList] = await Promise.all([
|
||||
sdk.forConsole.billing.listPaymentMethods(),
|
||||
sdk.forConsole.billing.listAddresses()
|
||||
sdk.forConsole.account.listPaymentMethods(),
|
||||
sdk.forConsole.account.listBillingAddresses()
|
||||
]);
|
||||
return {
|
||||
paymentMethods,
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, InputSelect, InputText } from '$lib/elements/forms';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
export let show = false;
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.createAddress(
|
||||
const response = await sdk.forConsole.account.createBillingAddress(
|
||||
country,
|
||||
address,
|
||||
city,
|
||||
@@ -54,9 +54,12 @@
|
||||
address2 ? address2 : undefined
|
||||
);
|
||||
trackEvent(Submit.BillingAddressCreate);
|
||||
let org: Organization = null;
|
||||
let org: Models.Organization<Record<string, unknown>> = null;
|
||||
if (organization) {
|
||||
org = await sdk.forConsole.billing.setBillingAddress(organization, response.$id);
|
||||
org = await sdk.forConsole.organizations.setBillingAddress(
|
||||
organization,
|
||||
response.$id
|
||||
);
|
||||
trackEvent(Submit.OrganizationBillingAddressUpdate);
|
||||
await invalidate(Dependencies.ORGANIZATION);
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
async function handleDelete() {
|
||||
try {
|
||||
await sdk.forConsole.billing.deleteAddress(selectedAddress.$id);
|
||||
await sdk.forConsole.account.deleteBillingAddress(selectedAddress.$id);
|
||||
await invalidate(Dependencies.PAYMENT_METHODS);
|
||||
showDelete = false;
|
||||
addNotification({
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
async function handleDelete() {
|
||||
try {
|
||||
await sdk.forConsole.billing.deletePaymentMethod(method);
|
||||
await sdk.forConsole.account.deletePaymentMethod(method);
|
||||
await invalidate(Dependencies.PAYMENT_METHODS);
|
||||
showDelete = false;
|
||||
addNotification({
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateAddress(
|
||||
await sdk.forConsole.account.updateBillingAddress(
|
||||
selectedAddress.$id,
|
||||
selectedAddress.country,
|
||||
selectedAddress.streetAddress,
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
export let isLinked = false;
|
||||
const currentYear = new Date().getFullYear();
|
||||
let error: string;
|
||||
let month: string;
|
||||
let month: number;
|
||||
let year: number;
|
||||
|
||||
async function handleSubmit() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updatePaymentMethod(
|
||||
await sdk.forConsole.account.updatePaymentMethod(
|
||||
selectedPaymentMethod.$id,
|
||||
month,
|
||||
year?.toString()
|
||||
year
|
||||
);
|
||||
trackEvent(Submit.PaymentMethodUpdate);
|
||||
invalidate(Dependencies.PAYMENT_METHODS);
|
||||
@@ -39,23 +39,23 @@
|
||||
|
||||
function createMonthOptions(year: number) {
|
||||
const months = [
|
||||
{ value: '01', label: '01' },
|
||||
{ value: '02', label: '02' },
|
||||
{ value: '03', label: '03' },
|
||||
{ value: '04', label: '04' },
|
||||
{ value: '05', label: '05' },
|
||||
{ value: '06', label: '06' },
|
||||
{ value: '07', label: '07' },
|
||||
{ value: '08', label: '08' },
|
||||
{ value: '09', label: '09' },
|
||||
{ value: '10', label: '10' },
|
||||
{ value: '11', label: '11' },
|
||||
{ value: '12', label: '12' }
|
||||
{ value: 1, label: '01' },
|
||||
{ value: 2, label: '02' },
|
||||
{ value: 3, label: '03' },
|
||||
{ value: 4, label: '04' },
|
||||
{ value: 5, label: '05' },
|
||||
{ value: 6, label: '06' },
|
||||
{ value: 7, label: '07' },
|
||||
{ value: 8, label: '08' },
|
||||
{ value: 9, label: '09' },
|
||||
{ value: 10, label: '10' },
|
||||
{ value: 11, label: '11' },
|
||||
{ value: 12, label: '12' }
|
||||
];
|
||||
if (!year) return months;
|
||||
if (year === currentYear) {
|
||||
const currentMonth = new Date().getMonth() + 1;
|
||||
return months.filter((option) => parseInt(option.value) >= currentMonth);
|
||||
return months.filter((option) => option.value >= currentMonth);
|
||||
} else {
|
||||
return months;
|
||||
}
|
||||
|
||||
@@ -4,23 +4,19 @@
|
||||
import { page } from '$app/state';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { CreditsApplied, SelectPaymentMethod } from '$lib/components/billing';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputSelect, InputTags, InputText } from '$lib/elements/forms';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { type PaymentList, type Plan } from '$lib/sdk/billing';
|
||||
import { type PaymentList } from '$lib/sdk/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import {
|
||||
organizationList,
|
||||
type Organization,
|
||||
type OrganizationError
|
||||
} from '$lib/stores/organization';
|
||||
import { organizationList, type OrganizationError } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { confirmPayment } from '$lib/stores/stripe.js';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
import { isOrganization, plansInfo, type Tier } from '$lib/stores/billing';
|
||||
import { isOrganization, isOrganizationError, plansInfo } from '$lib/stores/billing';
|
||||
import { Fieldset, Icon, Layout, Tooltip } from '@appwrite.io/pink-svelte';
|
||||
import { IconInfo } from '@appwrite.io/pink-icons-svelte';
|
||||
import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte';
|
||||
@@ -68,9 +64,9 @@
|
||||
let coupon: string;
|
||||
let couponData = data?.couponData;
|
||||
let campaign = data?.campaign;
|
||||
let billingPlan: Tier = BillingPlan.PRO;
|
||||
let billingPlan: BillingPlan = BillingPlan.Tier1;
|
||||
let tempOrgId = null;
|
||||
let currentPlan: Plan;
|
||||
let currentPlan: Models.BillingPlan;
|
||||
|
||||
$: onlyNewOrgs = (campaign && campaign.onlyNewOrgs) || (couponData && couponData.onlyNewOrgs);
|
||||
|
||||
@@ -91,7 +87,7 @@
|
||||
canSelectOrg = false;
|
||||
}
|
||||
if (campaign?.plan) {
|
||||
billingPlan = campaign.plan;
|
||||
billingPlan = campaign.plan as BillingPlan;
|
||||
}
|
||||
|
||||
if ($organizationList.total > 0 && tempOrgId === null) {
|
||||
@@ -113,7 +109,7 @@
|
||||
});
|
||||
|
||||
async function loadPaymentMethods() {
|
||||
const methodList = await sdk.forConsole.billing.listPaymentMethods();
|
||||
const methodList = await sdk.forConsole.account.listPaymentMethods();
|
||||
const filteredMethods = methodList.paymentMethods.filter((method) => !!method?.last4);
|
||||
methods = { paymentMethods: filteredMethods, total: filteredMethods.length };
|
||||
paymentMethodId =
|
||||
@@ -126,40 +122,40 @@
|
||||
if (!couponForm.checkValidity()) return;
|
||||
isSubmitting.set(true);
|
||||
try {
|
||||
let org: Organization | OrganizationError;
|
||||
let org: Models.Organization<Record<string, unknown>> | OrganizationError;
|
||||
// Create new org
|
||||
if (selectedOrgId === newOrgId) {
|
||||
org = await sdk.forConsole.billing.createOrganization(
|
||||
org = await sdk.forConsole.organizations.create(
|
||||
newOrgId,
|
||||
name,
|
||||
billingPlan,
|
||||
paymentMethodId,
|
||||
null,
|
||||
couponData.code ? couponData.code : null,
|
||||
collaborators,
|
||||
billingBudget,
|
||||
taxId
|
||||
couponData.code ? couponData.code : null,
|
||||
taxId,
|
||||
billingBudget
|
||||
);
|
||||
}
|
||||
|
||||
// Upgrade existing org
|
||||
else if (selectedOrg?.billingPlan !== billingPlan && isUpgrade()) {
|
||||
org = await sdk.forConsole.billing.updatePlan(
|
||||
org = await sdk.forConsole.organizations.updatePlan(
|
||||
selectedOrg.$id,
|
||||
billingPlan,
|
||||
paymentMethodId,
|
||||
null,
|
||||
couponData.code ? couponData.code : null,
|
||||
collaborators
|
||||
collaborators,
|
||||
couponData.code ? couponData.code : null
|
||||
);
|
||||
}
|
||||
// Existing pro org, apply credits
|
||||
else {
|
||||
org = selectedOrg;
|
||||
await sdk.forConsole.billing.addCredit(org.$id, couponData.code);
|
||||
await sdk.forConsole.organizations.addCredit(org.$id, couponData.code);
|
||||
}
|
||||
|
||||
if (!isOrganization(org) && org.status === 402) {
|
||||
if (isOrganizationError(org) && org.status === 402) {
|
||||
let clientSecret = org.clientSecret;
|
||||
let params = new URLSearchParams();
|
||||
params.append('type', 'payment_confirmed');
|
||||
@@ -205,7 +201,7 @@
|
||||
|
||||
async function addCoupon() {
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.getCoupon(coupon);
|
||||
const response = await sdk.forConsole.console.getCoupon(coupon);
|
||||
couponData = response;
|
||||
coupon = null;
|
||||
addNotification({
|
||||
@@ -220,23 +216,23 @@
|
||||
}
|
||||
}
|
||||
|
||||
$: selectedOrg = $organizationList?.teams?.find(
|
||||
(team) => team.$id === selectedOrgId
|
||||
) as Organization;
|
||||
$: selectedOrg = $organizationList?.teams?.find((team) => team.$id === selectedOrgId);
|
||||
|
||||
function getBillingPlan(): Tier | undefined {
|
||||
const campaignPlan =
|
||||
campaign?.plan && $plansInfo.get(campaign.plan) ? $plansInfo.get(campaign.plan) : null;
|
||||
function getBillingPlan(): BillingPlan | undefined {
|
||||
const plan = campaign.plan as BillingPlan;
|
||||
const campaignPlan = campaign?.plan && $plansInfo.get(plan) ? $plansInfo.get(plan) : null;
|
||||
const orgPlan =
|
||||
selectedOrg?.billingPlan && $plansInfo.get(selectedOrg.billingPlan)
|
||||
? $plansInfo.get(selectedOrg.billingPlan)
|
||||
selectedOrg?.billingPlan && $plansInfo.get(selectedOrg.billingPlan as BillingPlan)
|
||||
? $plansInfo.get(selectedOrg.billingPlan as BillingPlan)
|
||||
: null;
|
||||
|
||||
if (!campaignPlan || !orgPlan) {
|
||||
return;
|
||||
}
|
||||
|
||||
return campaignPlan.order > orgPlan.order ? campaign.plan : selectedOrg?.billingPlan;
|
||||
return campaignPlan.order > orgPlan.order
|
||||
? plan
|
||||
: (selectedOrg?.billingPlan as BillingPlan);
|
||||
}
|
||||
|
||||
$: if (selectedOrg) {
|
||||
@@ -246,7 +242,7 @@
|
||||
$: {
|
||||
if (selectedOrgId) {
|
||||
(async () => {
|
||||
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(selectedOrgId);
|
||||
currentPlan = await sdk.forConsole.organizations.getPlan(selectedOrgId);
|
||||
})();
|
||||
}
|
||||
}
|
||||
@@ -271,7 +267,7 @@
|
||||
placeholder="Select organization"
|
||||
id="organization" />
|
||||
{/if}
|
||||
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)}
|
||||
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)}
|
||||
{#if selectedOrgId === newOrgId}
|
||||
<InputText
|
||||
label="Organization name"
|
||||
@@ -297,10 +293,10 @@
|
||||
{/if}
|
||||
</Layout.Stack>
|
||||
</Fieldset>
|
||||
{#if (selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)) || (!data?.couponData?.code && selectedOrgId)}
|
||||
{#if (selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)) || (!data?.couponData?.code && selectedOrgId)}
|
||||
<Fieldset legend="Payment">
|
||||
<Layout.Stack gap="xl">
|
||||
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.PRO || !selectedOrg?.paymentMethodId)}
|
||||
{#if selectedOrgId && (selectedOrg?.billingPlan !== BillingPlan.Tier1 || !selectedOrg?.paymentMethodId)}
|
||||
<SelectPaymentMethod
|
||||
bind:methods
|
||||
bind:value={paymentMethodId}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
import { base } from '$app/paths';
|
||||
import type { Coupon } from '$lib/sdk/billing.js';
|
||||
import type { Campaign } from '$lib/stores/campaigns.js';
|
||||
import { sdk } from '$lib/stores/sdk.js';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
|
||||
export const load = async ({ url }) => {
|
||||
// Has promo code
|
||||
if (url.searchParams.has('code')) {
|
||||
let couponData: Coupon;
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
const code = url.searchParams.get('code');
|
||||
try {
|
||||
couponData = await sdk.forConsole.billing.getCouponAccount(code);
|
||||
couponData = await sdk.forConsole.account.getCoupon(code);
|
||||
if (couponData.campaign) {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
|
||||
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
|
||||
}
|
||||
return { couponData, campaign };
|
||||
} catch (e) {
|
||||
@@ -23,9 +23,9 @@ export const load = async ({ url }) => {
|
||||
// Has campaign
|
||||
else if (url.searchParams.has('campaign')) {
|
||||
const campaignId = url.searchParams.get('campaign');
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
try {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
|
||||
campaign = await sdk.forConsole.console.getCampaign(campaignId);
|
||||
return { campaign };
|
||||
} catch (e) {
|
||||
redirect(303, base);
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { PlanComparisonBox, PlanSelection, SelectPaymentMethod } from '$lib/components/billing';
|
||||
import ValidateCreditModal from '$lib/components/billing/validateCreditModal.svelte';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button, Form, InputTags, InputText } from '$lib/elements/forms';
|
||||
import { Wizard } from '$lib/layout';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import { isOrganization, tierToPlan } from '$lib/stores/billing';
|
||||
import { isOrganization, isOrganizationError, tierToPlan } from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { type OrganizationError, type Organization } from '$lib/stores/organization';
|
||||
import { type OrganizationError } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { confirmPayment } from '$lib/stores/stripe';
|
||||
import { ID } from '@appwrite.io/console';
|
||||
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
|
||||
import { IconPlus } from '@appwrite.io/pink-icons-svelte';
|
||||
import { Divider, Fieldset, Icon, Layout, Link, Typography } from '@appwrite.io/pink-svelte';
|
||||
import { writable } from 'svelte/store';
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
export let data;
|
||||
|
||||
let selectedPlan: BillingPlan = data.plan as BillingPlan;
|
||||
let selectedPlan: BillingPlan = data.plan;
|
||||
let selectedCoupon: Partial<Coupon> | null = data.coupon;
|
||||
let previousPage: string = base;
|
||||
let showExitModal = false;
|
||||
@@ -32,7 +32,7 @@
|
||||
let isSubmitting = writable(false);
|
||||
|
||||
let name: string;
|
||||
let billingPlan: BillingPlan = BillingPlan.FREE;
|
||||
let billingPlan: BillingPlan = BillingPlan.Tier0;
|
||||
let paymentMethodId: string;
|
||||
let collaborators: string[] = [];
|
||||
let couponData: Partial<Coupon> = {
|
||||
@@ -53,7 +53,7 @@
|
||||
if (page.url.searchParams.has('coupon')) {
|
||||
const coupon = page.url.searchParams.get('coupon');
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
|
||||
const response = await sdk.forConsole.account.getCoupon(coupon);
|
||||
couponData = response;
|
||||
} catch (e) {
|
||||
couponData = {
|
||||
@@ -76,7 +76,7 @@
|
||||
data?.hasFreeOrganizations ||
|
||||
(page.url.searchParams.has('type') && page.url.searchParams.get('type') === 'createPro')
|
||||
) {
|
||||
billingPlan = BillingPlan.PRO;
|
||||
billingPlan = BillingPlan.Tier1;
|
||||
}
|
||||
if (page.url.searchParams.has('type')) {
|
||||
const type = page.url.searchParams.get('type');
|
||||
@@ -110,32 +110,26 @@
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
let org: Organization | OrganizationError;
|
||||
let org: Models.Organization<Record<string, unknown>> | OrganizationError;
|
||||
|
||||
if (selectedPlan === BillingPlan.FREE) {
|
||||
org = await sdk.forConsole.billing.createOrganization(
|
||||
ID.unique(),
|
||||
name,
|
||||
BillingPlan.FREE,
|
||||
null,
|
||||
null
|
||||
);
|
||||
if (selectedPlan === BillingPlan.Tier0) {
|
||||
org = await sdk.forConsole.organizations.create(ID.unique(), name, selectedPlan);
|
||||
} else {
|
||||
org = await sdk.forConsole.billing.createOrganization(
|
||||
org = await sdk.forConsole.organizations.create(
|
||||
ID.unique(),
|
||||
name,
|
||||
selectedPlan,
|
||||
paymentMethodId,
|
||||
null,
|
||||
couponData.code ? couponData.code : null,
|
||||
collaborators,
|
||||
billingBudget,
|
||||
taxId
|
||||
couponData.code ? couponData.code : null,
|
||||
taxId,
|
||||
billingBudget
|
||||
);
|
||||
|
||||
if (!isOrganization(org) && org.status === 402) {
|
||||
let clientSecret = org.clientSecret;
|
||||
let params = new URLSearchParams();
|
||||
if (isOrganizationError(org) && org.status === 402) {
|
||||
const clientSecret = org.clientSecret;
|
||||
const params = new URLSearchParams();
|
||||
params.append('type', 'payment_confirmed');
|
||||
params.append('id', org.teamId);
|
||||
for (const [key, value] of page.url.searchParams.entries()) {
|
||||
@@ -208,7 +202,7 @@
|
||||
anyOrgFree={data.hasFreeOrganizations}
|
||||
isNewOrg />
|
||||
</Fieldset>
|
||||
{#if selectedPlan !== BillingPlan.FREE}
|
||||
{#if selectedPlan !== BillingPlan.Tier0}
|
||||
<Fieldset legend="Payment">
|
||||
<SelectPaymentMethod
|
||||
methods={data.paymentMethods}
|
||||
@@ -236,7 +230,7 @@
|
||||
</Layout.Stack>
|
||||
</Form>
|
||||
<svelte:fragment slot="aside">
|
||||
{#if selectedPlan !== BillingPlan.FREE}
|
||||
{#if selectedPlan !== BillingPlan.Tier0}
|
||||
<EstimatedTotalBox
|
||||
billingPlan={selectedPlan}
|
||||
{collaborators}
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { BillingPlan } from '@appwrite.io/console';
|
||||
|
||||
export const load: PageLoad = async ({ url, parent }) => {
|
||||
const { organizations } = await parent();
|
||||
const [coupon, paymentMethods] = await Promise.all([
|
||||
getCoupon(url),
|
||||
sdk.forConsole.billing.listPaymentMethods()
|
||||
sdk.forConsole.account.listPaymentMethods()
|
||||
]);
|
||||
let plan = getPlanFromUrl(url);
|
||||
const hasFreeOrganizations = organizations.teams?.some(
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.Tier0
|
||||
);
|
||||
if (plan === BillingPlan.FREE && hasFreeOrganizations) {
|
||||
plan = BillingPlan.PRO;
|
||||
if (plan === BillingPlan.Tier0 && hasFreeOrganizations) {
|
||||
plan = BillingPlan.Tier1;
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -34,14 +34,14 @@ function getPlanFromUrl(url: URL): BillingPlan | null {
|
||||
return plan as BillingPlan;
|
||||
}
|
||||
}
|
||||
return BillingPlan.FREE;
|
||||
return BillingPlan.Tier0;
|
||||
}
|
||||
|
||||
async function getCoupon(url: URL): Promise<Coupon | null> {
|
||||
if (url.searchParams.has('code')) {
|
||||
const coupon = url.searchParams.get('code');
|
||||
try {
|
||||
return sdk.forConsole.billing.getCoupon(coupon);
|
||||
return sdk.forConsole.console.getCoupon(coupon);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@ import type { PageLoad } from './$types';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { isOrganization, tierToPlan } from '$lib/stores/billing';
|
||||
import { ID, Query } from '@appwrite.io/console';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { isOrganization, isOrganizationError, tierToPlan } from '$lib/stores/billing';
|
||||
import { BillingPlan, ID, Query } from '@appwrite.io/console';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
@@ -14,15 +13,13 @@ export const load: PageLoad = async ({ parent }) => {
|
||||
if (!organizations?.total) {
|
||||
try {
|
||||
if (isCloud) {
|
||||
const org = await sdk.forConsole.billing.createOrganization(
|
||||
const org = await sdk.forConsole.organizations.create(
|
||||
ID.unique(),
|
||||
'Personal projects',
|
||||
BillingPlan.FREE,
|
||||
null,
|
||||
null
|
||||
BillingPlan.Tier0
|
||||
);
|
||||
trackEvent(Submit.OrganizationCreate, {
|
||||
plan: tierToPlan(BillingPlan.FREE)?.name,
|
||||
plan: tierToPlan(BillingPlan.Tier0)?.name,
|
||||
budget_cap_enabled: false,
|
||||
members_invited: 0
|
||||
});
|
||||
@@ -32,7 +29,7 @@ export const load: PageLoad = async ({ parent }) => {
|
||||
organization: org,
|
||||
regions: await sdk.forConsole.billing.listRegions(org.$id)
|
||||
};
|
||||
} else {
|
||||
} else if (isOrganizationError(org)) {
|
||||
const e = new Error(org.message, {
|
||||
cause: org
|
||||
});
|
||||
|
||||
@@ -12,8 +12,8 @@ import { get } from 'svelte/store';
|
||||
import { preferences } from '$lib/stores/preferences';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { defaultRoles, defaultScopes } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import { loadAvailableRegions } from '$routes/(console)/regions';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.ORGANIZATION);
|
||||
@@ -21,14 +21,14 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.PAYMENT_METHODS);
|
||||
let roles = isCloud ? [] : defaultRoles;
|
||||
let scopes = isCloud ? [] : defaultScopes;
|
||||
let currentPlan: Plan = null;
|
||||
let currentPlan: Models.BillingPlan = null;
|
||||
|
||||
try {
|
||||
if (isCloud) {
|
||||
const res = await sdk.forConsole.billing.getRoles(params.organization);
|
||||
const res = await sdk.forConsole.organizations.getScopes(params.organization);
|
||||
roles = res.roles;
|
||||
scopes = res.scopes;
|
||||
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(params.organization);
|
||||
currentPlan = await sdk.forConsole.organizations.getPlan(params.organization);
|
||||
if (scopes.includes('billing.read')) {
|
||||
await failedInvoice.load(params.organization);
|
||||
if (get(failedInvoice)) {
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
page.url.searchParams.get('type') === 'confirmation'
|
||||
) {
|
||||
const invoiceId = page.url.searchParams.get('invoice');
|
||||
const invoice = await sdk.forConsole.billing.getInvoice(
|
||||
const invoice = await sdk.forConsole.organizations.getInvoice(
|
||||
page.params.organization,
|
||||
invoiceId
|
||||
);
|
||||
@@ -62,7 +62,7 @@
|
||||
page.url.searchParams.get('type') === 'validate-invoice'
|
||||
) {
|
||||
const invoiceId = page.url.searchParams.get('invoice');
|
||||
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoiceId);
|
||||
await sdk.forConsole.organizations.validateInvoice($organization.$id, invoiceId);
|
||||
invalidate(Dependencies.INVOICES);
|
||||
invalidate(Dependencies.ORGANIZATION);
|
||||
}
|
||||
@@ -72,7 +72,7 @@
|
||||
page.url.searchParams.get('type') === 'retry'
|
||||
) {
|
||||
const invoiceId = page.url.searchParams.get('invoice');
|
||||
const invoice = await sdk.forConsole.billing.getInvoice(
|
||||
const invoice = await sdk.forConsole.organizations.getInvoice(
|
||||
page.params.organization,
|
||||
invoiceId
|
||||
);
|
||||
@@ -120,9 +120,13 @@
|
||||
{/if}
|
||||
{#if $organization?.billingPlanDowngrade}
|
||||
<Alert.Inline status="info">
|
||||
Your organization has changed to {tierToPlan($organization?.billingPlanDowngrade).name} plan.
|
||||
You will continue to have access to {tierToPlan($organization?.billingPlan).name} plan features
|
||||
until your billing period ends on {toLocaleDate($organization.billingNextInvoiceDate)}.
|
||||
Your organization has changed to {tierToPlan(
|
||||
$organization?.billingPlanDowngrade as unknown as string
|
||||
).name} plan. You will continue to have access to {tierToPlan(
|
||||
$organization?.billingPlan
|
||||
).name} plan features until your billing period ends on {toLocaleDate(
|
||||
$organization.billingNextInvoiceDate
|
||||
)}.
|
||||
</Alert.Inline>
|
||||
{/if}
|
||||
<Typography.Title>Billing</Typography.Title>
|
||||
|
||||
@@ -31,7 +31,7 @@ export const load: PageLoad = async ({ parent, depends }) => {
|
||||
*/
|
||||
let billingAggregation = null;
|
||||
try {
|
||||
billingAggregation = await sdk.forConsole.billing.getAggregation(
|
||||
billingAggregation = await sdk.forConsole.organizations.getAggregation(
|
||||
organization.$id,
|
||||
(organization as Organization)?.billingAggregationId
|
||||
);
|
||||
@@ -41,7 +41,7 @@ export const load: PageLoad = async ({ parent, depends }) => {
|
||||
|
||||
let billingInvoice = null;
|
||||
try {
|
||||
billingInvoice = await sdk.forConsole.billing.getInvoice(
|
||||
billingInvoice = await sdk.forConsole.organizations.getInvoice(
|
||||
organization.$id,
|
||||
(organization as Organization)?.billingInvoiceId
|
||||
);
|
||||
@@ -51,10 +51,10 @@ export const load: PageLoad = async ({ parent, depends }) => {
|
||||
|
||||
const [paymentMethods, addressList, billingAddress, creditList, aggregationBillingPlan] =
|
||||
await Promise.all([
|
||||
sdk.forConsole.billing.listPaymentMethods(),
|
||||
sdk.forConsole.billing.listAddresses(),
|
||||
sdk.forConsole.account.listPaymentMethods(),
|
||||
sdk.forConsole.account.listBillingAddresses(),
|
||||
billingAddressPromise,
|
||||
sdk.forConsole.billing.listCredits(organization.$id),
|
||||
sdk.forConsole.organizations.listCredits(organization.$id),
|
||||
sdk.forConsole.billing.getPlan(billingAggregation?.plan ?? organization.billingPlan)
|
||||
]);
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
async function redeem() {
|
||||
try {
|
||||
await sdk.forConsole.billing.addCredit($organization.$id, coupon);
|
||||
await sdk.forConsole.organizations.addCredit($organization.$id, coupon);
|
||||
show = false;
|
||||
await invalidate(Dependencies.CREDIT);
|
||||
await invalidate(Dependencies.ORGANIZATION);
|
||||
|
||||
@@ -18,12 +18,15 @@
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethod(
|
||||
await sdk.forConsole.organizations.setDefaultPaymentMethod(
|
||||
$organization.$id,
|
||||
$addCreditWizardStore.paymentMethodId
|
||||
);
|
||||
|
||||
await sdk.forConsole.billing.addCredit($organization.$id, $addCreditWizardStore.coupon);
|
||||
await sdk.forConsole.organizations.addCredit(
|
||||
$organization.$id,
|
||||
$addCreditWizardStore.coupon
|
||||
);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `Credit has been added to ${$organization.name}`
|
||||
|
||||
@@ -42,7 +42,7 @@
|
||||
|
||||
async function request() {
|
||||
if (!$organization?.$id) return;
|
||||
creditList = await sdk.forConsole.billing.listCredits($organization.$id, [
|
||||
creditList = await sdk.forConsole.organizations.listCredits($organization.$id, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset)
|
||||
]);
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
async function addAddress(addressId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setBillingAddress($organization.$id, addressId);
|
||||
await sdk.forConsole.organizations.setBillingAddress($organization.$id, addressId);
|
||||
|
||||
await invalidate(Dependencies.ADDRESS);
|
||||
await invalidate(Dependencies.ORGANIZATION);
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
async function updateBudget() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateBudget(
|
||||
await sdk.forConsole.organizations.updateBudget(
|
||||
$organization.$id,
|
||||
$organization.billingBudget,
|
||||
alerts
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
async function updateBudget() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateBudget(
|
||||
await sdk.forConsole.organizations.updateBudget(
|
||||
$organization.$id,
|
||||
budget,
|
||||
$organization.budgetAlerts
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
<Modal title="Cancel plan change" onSubmit={cancelDowngrade} bind:show={showCancel} bind:error>
|
||||
<p>
|
||||
Your organization is set to change to <strong>
|
||||
{tierToPlan($organization?.billingPlanDowngrade).name}</strong>
|
||||
{tierToPlan($organization?.billingPlanDowngrade as unknown as string).name}</strong>
|
||||
plan on <strong> {toLocaleDate($organization.billingNextInvoiceDate)}</strong>. Are you sure
|
||||
you want to cancel this change and keep your current plan?
|
||||
</p>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
if ($organization?.billingPlan !== BillingPlan.FREE && !hasOtherMethod) return;
|
||||
|
||||
try {
|
||||
await sdk.forConsole.billing.removeOrganizationPaymentMethod($organization.$id);
|
||||
await sdk.forConsole.organizations.deleteDefaultPaymentMethod($organization.$id);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `The payment method has been removed from ${$organization.name}`
|
||||
@@ -39,7 +39,7 @@
|
||||
showDelete = false;
|
||||
|
||||
try {
|
||||
await sdk.forConsole.billing.removeOrganizationPaymentMethodBackup($organization.$id);
|
||||
await sdk.forConsole.organizations.deleteBackupPaymentMethod($organization.$id);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `The payment method has been removed from ${$organization.name}`
|
||||
|
||||
@@ -4,9 +4,8 @@
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import { formatCurrency } from '$lib/helpers/numbers';
|
||||
import type { Invoice, InvoiceList } from '$lib/sdk/billing';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import { onMount } from 'svelte';
|
||||
import { trackEvent } from '$lib/actions/analytics';
|
||||
import { selectedInvoice, showRetryModal } from './store';
|
||||
@@ -30,7 +29,7 @@
|
||||
import { base } from '$app/paths';
|
||||
|
||||
let offset = 0;
|
||||
let invoiceList: InvoiceList = {
|
||||
let invoiceList: Models.InvoiceList = {
|
||||
invoices: [],
|
||||
total: 0
|
||||
};
|
||||
@@ -41,7 +40,7 @@
|
||||
|
||||
async function request() {
|
||||
// isLoadingInvoices = true;
|
||||
invoiceList = await sdk.forConsole.billing.listInvoices(page.params.organization, [
|
||||
invoiceList = await sdk.forConsole.organizations.listInvoices(page.params.organization, [
|
||||
Query.limit(limit),
|
||||
Query.offset(offset),
|
||||
Query.orderDesc('$createdAt')
|
||||
@@ -53,7 +52,7 @@
|
||||
request();
|
||||
}
|
||||
|
||||
function retryPayment(invoice: Invoice) {
|
||||
function retryPayment(invoice: Models.Invoice) {
|
||||
$selectedInvoice = invoice;
|
||||
$showRetryModal = true;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
async function addPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethod(
|
||||
await sdk.forConsole.organizations.setDefaultPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
@@ -66,7 +66,7 @@
|
||||
|
||||
async function addBackupPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethodBackup(
|
||||
await sdk.forConsole.organizations.setBackupPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
const today = new Date();
|
||||
const isTrial =
|
||||
new Date($organization?.billingStartDate).getTime() - today.getTime() > 0 &&
|
||||
$plansInfo.get($organization.billingPlan)?.trialDays;
|
||||
$plansInfo.get($organization.billingPlan)?.trial;
|
||||
const extraUsage = currentInvoice ? currentInvoice.amount - currentPlan?.price : 0;
|
||||
|
||||
function usageNameToLabel(name: string): string {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
async function removeAddress() {
|
||||
try {
|
||||
await sdk.forConsole.billing.removeBillingAddress($organization.$id);
|
||||
await sdk.forConsole.organizations.deleteBillingAddress($organization.$id);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
message: `The billing address has been removed from ${$organization.name}`
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
onMount(async () => {
|
||||
loading = true;
|
||||
addresses = await sdk.forConsole.billing.listAddresses();
|
||||
addresses = await sdk.forConsole.account.listBillingAddresses();
|
||||
|
||||
const firstNonCurrentAddress = addresses?.billingAddresses?.find(
|
||||
(address) => address.$id !== $organization?.billingAddressId
|
||||
@@ -65,7 +65,7 @@
|
||||
if (selectedAddress === $organization.billingAddressId) {
|
||||
show = false;
|
||||
} else if (selectedAddress === '$new') {
|
||||
const address = await sdk.forConsole.billing.createAddress(
|
||||
const address = await sdk.forConsole.account.createBillingAddress(
|
||||
country,
|
||||
streetAddress,
|
||||
city,
|
||||
@@ -73,7 +73,10 @@
|
||||
postalCode ? postalCode : undefined,
|
||||
addressLine2 ? postalCode : undefined
|
||||
);
|
||||
await sdk.forConsole.billing.setBillingAddress($organization.$id, address.$id);
|
||||
await sdk.forConsole.organizations.setBillingAddress(
|
||||
$organization.$id,
|
||||
address.$id
|
||||
);
|
||||
|
||||
invalidate(Dependencies.ORGANIZATION);
|
||||
invalidate(Dependencies.ADDRESS);
|
||||
@@ -88,7 +91,10 @@
|
||||
message: `Your billing address has been updated`
|
||||
});
|
||||
} else {
|
||||
await sdk.forConsole.billing.setBillingAddress($organization.$id, selectedAddress);
|
||||
await sdk.forConsole.organizations.setBillingAddress(
|
||||
$organization.$id,
|
||||
selectedAddress
|
||||
);
|
||||
|
||||
invalidate(Dependencies.ORGANIZATION);
|
||||
invalidate(Dependencies.ADDRESS);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
let error: string;
|
||||
|
||||
onMount(async () => {
|
||||
methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
methods = await sdk.forConsole.account.listPaymentMethods();
|
||||
|
||||
if (!$organization.paymentMethodId && !$organization.backupPaymentMethodId) {
|
||||
selectedPaymentMethodId = methods?.total ? methods.paymentMethods[0].$id : null;
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
async function addPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethod(
|
||||
await sdk.forConsole.organizations.setDefaultPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
@@ -79,7 +79,7 @@
|
||||
|
||||
async function addBackupPaymentMethod(paymentMethodId: string) {
|
||||
try {
|
||||
await sdk.forConsole.billing.setOrganizationPaymentMethodBackup(
|
||||
await sdk.forConsole.organizations.setBackupPaymentMethod(
|
||||
$organization.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import { FakeModal } from '$lib/components';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import type { Invoice } from '$lib/sdk/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { page } from '$app/state';
|
||||
@@ -16,9 +15,10 @@
|
||||
import { getApiEndpoint, sdk } from '$lib/stores/sdk';
|
||||
import { formatCurrency } from '$lib/helpers/numbers';
|
||||
import { base } from '$app/paths';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export let show = false;
|
||||
export let invoice: Invoice;
|
||||
export let invoice: Models.Invoice;
|
||||
let error: string = null;
|
||||
let isButtonDisabled = false;
|
||||
let name: string;
|
||||
@@ -49,7 +49,7 @@
|
||||
if (paymentMethodId === null) {
|
||||
try {
|
||||
const method = await submitStripeCard(name, $organization.$id);
|
||||
const card = await sdk.forConsole.billing.getPaymentMethod(method.$id);
|
||||
const card = await sdk.forConsole.account.getPaymentMethod(method.$id);
|
||||
if (card?.last4) {
|
||||
paymentMethodId = card.$id;
|
||||
} else {
|
||||
@@ -66,11 +66,12 @@
|
||||
if (setAsDefault) {
|
||||
await sdk.forConsole.billing.setDefaultPaymentMethod(paymentMethodId);
|
||||
}
|
||||
const { clientSecret, status } = await sdk.forConsole.billing.retryPayment(
|
||||
$organization.$id,
|
||||
invoice.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
const { clientSecret, status } =
|
||||
await sdk.forConsole.organizations.createInvoicePayment(
|
||||
$organization.$id,
|
||||
invoice.$id,
|
||||
paymentMethodId
|
||||
);
|
||||
|
||||
if (status !== 'succeeded' && status !== 'cancelled') {
|
||||
// probably still pending, confirm via stripe!
|
||||
@@ -81,7 +82,7 @@
|
||||
`${base}/organization-${$organization.$id}/billing?type=validate-invoice&invoice=${invoice.$id}`
|
||||
);
|
||||
|
||||
await sdk.forConsole.billing.updateInvoiceStatus($organization.$id, invoice.$id);
|
||||
await sdk.forConsole.organizations.validateInvoice($organization.$id, invoice.$id);
|
||||
}
|
||||
|
||||
invalidate(Dependencies.ORGANIZATION);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { WizardStepsType } from '$lib/layout/wizardWithSteps.svelte';
|
||||
import type { AggregationList, Invoice } from '$lib/sdk/billing';
|
||||
import type { AggregationList } from '$lib/sdk/billing';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
|
||||
export const aggregationList = derived(
|
||||
@@ -14,5 +15,5 @@ export const addCreditWizardStore = writable<{ coupon: string; paymentMethodId:
|
||||
paymentMethodId: null
|
||||
});
|
||||
|
||||
export const selectedInvoice = writable<Invoice>(null);
|
||||
export const selectedInvoice = writable<Models.Invoice>(null);
|
||||
export const showRetryModal = writable(false);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
async function updateTaxId() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updateTaxId($organization.$id, taxId);
|
||||
await sdk.forConsole.organizations.setBillingTaxId($organization.$id, taxId);
|
||||
await invalidate(Dependencies.ORGANIZATION);
|
||||
addNotification({
|
||||
type: 'success',
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
async function validateCoupon() {
|
||||
if (couponData?.status === 'active') return;
|
||||
try {
|
||||
const response = await sdk.forConsole.billing.getCouponAccount(coupon);
|
||||
const response = await sdk.forConsole.account.getCoupon(coupon);
|
||||
couponData = response;
|
||||
$addCreditWizardStore.coupon = coupon;
|
||||
coupon = null;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
let name: string;
|
||||
|
||||
onMount(async () => {
|
||||
methods = await sdk.forConsole.billing.listPaymentMethods();
|
||||
methods = await sdk.forConsole.account.listPaymentMethods();
|
||||
$addCreditWizardStore.paymentMethodId =
|
||||
methods.paymentMethods.find((method) => !!method?.last4)?.$id ?? null;
|
||||
});
|
||||
|
||||
@@ -11,7 +11,12 @@
|
||||
import { formatCurrency } from '$lib/helpers/numbers.js';
|
||||
import { Wizard } from '$lib/layout';
|
||||
import { type Coupon } from '$lib/sdk/billing';
|
||||
import { isOrganization, plansInfo, tierToPlan } from '$lib/stores/billing';
|
||||
import {
|
||||
isOrganization,
|
||||
isOrganizationError,
|
||||
plansInfo,
|
||||
tierToPlan
|
||||
} from '$lib/stores/billing';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { currentPlan, organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
@@ -31,10 +36,11 @@
|
||||
import { writable } from 'svelte/store';
|
||||
import { onMount } from 'svelte';
|
||||
import EstimatedTotalBox from '$lib/components/billing/estimatedTotalBox.svelte';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types.js';
|
||||
|
||||
export let data;
|
||||
|
||||
let selectedPlan: BillingPlan = data.plan as BillingPlan;
|
||||
let selectedPlan: BillingPlan = data.plan;
|
||||
let selectedCoupon: Partial<Coupon> | null = data.coupon;
|
||||
let previousPage: string = base;
|
||||
let showExitModal = false;
|
||||
@@ -63,7 +69,7 @@
|
||||
if (page.url.searchParams.has('code')) {
|
||||
const coupon = page.url.searchParams.get('code');
|
||||
try {
|
||||
couponData = await sdk.forConsole.billing.getCouponAccount(coupon);
|
||||
couponData = await sdk.forConsole.account.getCoupon(coupon);
|
||||
} catch (e) {
|
||||
couponData = {
|
||||
code: null,
|
||||
@@ -74,7 +80,7 @@
|
||||
}
|
||||
if (page.url.searchParams.has('plan')) {
|
||||
const plan = page.url.searchParams.get('plan');
|
||||
if (plan && plan in BillingPlan) {
|
||||
if (plan && isValueOfStringEnum(BillingPlan, plan)) {
|
||||
selectedPlan = plan as BillingPlan;
|
||||
}
|
||||
}
|
||||
@@ -87,10 +93,10 @@
|
||||
await validate(organizationId, invites);
|
||||
}
|
||||
}
|
||||
if ($currentPlan?.$id === BillingPlan.SCALE) {
|
||||
selectedPlan = BillingPlan.SCALE;
|
||||
if ($currentPlan?.$id === BillingPlan.Tier2) {
|
||||
selectedPlan = BillingPlan.Tier2;
|
||||
} else {
|
||||
selectedPlan = BillingPlan.PRO;
|
||||
selectedPlan = BillingPlan.Tier1;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -104,7 +110,7 @@
|
||||
|
||||
async function downgrade() {
|
||||
try {
|
||||
await sdk.forConsole.billing.updatePlan(
|
||||
await sdk.forConsole.organizations.updatePlan(
|
||||
data.organization.$id,
|
||||
selectedPlan,
|
||||
paymentMethodId,
|
||||
@@ -186,18 +192,18 @@
|
||||
!data?.members?.memberships?.find((m) => m.userEmail === collaborator)
|
||||
);
|
||||
}
|
||||
const org = await sdk.forConsole.billing.updatePlan(
|
||||
const org = await sdk.forConsole.organizations.updatePlan(
|
||||
data.organization.$id,
|
||||
selectedPlan,
|
||||
paymentMethodId,
|
||||
null,
|
||||
couponData?.code,
|
||||
newCollaborators,
|
||||
billingBudget,
|
||||
taxId ? taxId : null
|
||||
couponData?.code,
|
||||
taxId ? taxId : null,
|
||||
billingBudget
|
||||
);
|
||||
|
||||
if (!isOrganization(org) && org.status == 402) {
|
||||
if (isOrganizationError(org) && org.status == 402) {
|
||||
let clientSecret = org.clientSecret;
|
||||
let params = new URLSearchParams();
|
||||
for (const [key, value] of page.url.searchParams.entries()) {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import type { PageLoad } from './$types';
|
||||
import type { Coupon } from '$lib/sdk/billing';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import { BillingPlan } from '@appwrite.io/console';
|
||||
|
||||
export const load: PageLoad = async ({ depends, parent, url }) => {
|
||||
const { members, organization, currentPlan, organizations } = await parent();
|
||||
@@ -10,20 +11,20 @@ export const load: PageLoad = async ({ depends, parent, url }) => {
|
||||
|
||||
const [coupon, paymentMethods] = await Promise.all([
|
||||
getCoupon(url),
|
||||
sdk.forConsole.billing.listPaymentMethods()
|
||||
sdk.forConsole.account.listPaymentMethods()
|
||||
]);
|
||||
|
||||
let plan = getPlanFromUrl(url);
|
||||
|
||||
if (organization?.billingPlan === BillingPlan.SCALE) {
|
||||
plan = BillingPlan.SCALE;
|
||||
if (organization?.billingPlan === BillingPlan.Tier2) {
|
||||
plan = BillingPlan.Tier2;
|
||||
} else {
|
||||
plan = BillingPlan.PRO;
|
||||
plan = BillingPlan.Tier1;
|
||||
}
|
||||
|
||||
const selfService = currentPlan?.selfService ?? true;
|
||||
const hasFreeOrgs = organizations.teams?.some(
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.FREE
|
||||
(org) => (org as Organization)?.billingPlan === BillingPlan.Tier0
|
||||
);
|
||||
|
||||
return {
|
||||
@@ -49,7 +50,7 @@ async function getCoupon(url: URL): Promise<Coupon | null> {
|
||||
if (url.searchParams.has('code')) {
|
||||
const coupon = url.searchParams.get('code');
|
||||
try {
|
||||
return sdk.forConsole.billing.getCoupon(coupon);
|
||||
return sdk.forConsole.console.getCoupon(coupon);
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ export const load = async ({ parent, depends }) => {
|
||||
|
||||
const organizations = !isCloud
|
||||
? await sdk.forConsole.teams.list()
|
||||
: await sdk.forConsole.billing.listOrganization();
|
||||
: await sdk.forConsole.organizations.list();
|
||||
|
||||
const { domain } = await parent();
|
||||
return {
|
||||
|
||||
@@ -91,7 +91,7 @@
|
||||
{:else if isCloud && $organization?.billingPlan === BillingPlan.FREE}
|
||||
<Badge variant="secondary" content="Free"></Badge>
|
||||
{/if}
|
||||
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.FREE && $plansInfo.get($organization.billingPlan)?.trialDays}
|
||||
{#if isCloud && $organization?.billingTrialStartDate && $daysLeftInTrial > 0 && $organization.billingPlan !== BillingPlan.FREE && $plansInfo.get($organization.billingPlan)?.trial}
|
||||
<Tooltip>
|
||||
<Badge variant="secondary" content="Trial" />
|
||||
<svelte:fragment slot="tooltip">
|
||||
|
||||
+4
-1
@@ -4,7 +4,10 @@ import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
// verify invoice exists
|
||||
const invoice = await sdk.forConsole.billing.getInvoice(params.organization, params.invoiceId);
|
||||
const invoice = await sdk.forConsole.organizations.getInvoice(
|
||||
params.organization,
|
||||
params.invoiceId
|
||||
);
|
||||
const endpoint = getApiEndpoint();
|
||||
|
||||
return redirect(
|
||||
|
||||
@@ -4,7 +4,10 @@ import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => {
|
||||
// verify invoice exists
|
||||
const invoice = await sdk.forConsole.billing.getInvoice(params.organization, params.invoiceId);
|
||||
const invoice = await sdk.forConsole.organizations.getInvoice(
|
||||
params.organization,
|
||||
params.invoiceId
|
||||
);
|
||||
const endpoint = getApiEndpoint();
|
||||
|
||||
return redirect(
|
||||
|
||||
@@ -9,7 +9,7 @@ export const load: PageLoad = async ({ depends, params }) => {
|
||||
|
||||
const [projects, invoices] = await Promise.all([
|
||||
sdk.forConsole.projects.list([Query.equal('teamId', params.organization)]),
|
||||
isCloud ? sdk.forConsole.billing.listInvoices(params.organization) : undefined
|
||||
isCloud ? sdk.forConsole.organizations.listInvoices(params.organization) : undefined
|
||||
]);
|
||||
|
||||
return {
|
||||
|
||||
+4
-3
@@ -16,10 +16,11 @@
|
||||
import { Table, Tabs, Alert } from '@appwrite.io/pink-svelte';
|
||||
import DeleteOrganizationEstimation from './deleteOrganizationEstimation.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import type { EstimationDeleteOrganization, InvoiceList } from '$lib/sdk/billing';
|
||||
import type { EstimationDeleteOrganization } from '$lib/sdk/billing';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export let showDelete = false;
|
||||
export let invoices: InvoiceList;
|
||||
export let invoices: Models.InvoiceList;
|
||||
let error: string = null;
|
||||
|
||||
let selectedTab = 'projects';
|
||||
@@ -29,7 +30,7 @@
|
||||
async function deleteOrg() {
|
||||
try {
|
||||
if (isCloud) {
|
||||
await sdk.forConsole.billing.deleteOrganization($organization.$id);
|
||||
await sdk.forConsole.organizations.delete($organization.$id);
|
||||
} else {
|
||||
await sdk.forConsole.teams.delete($organization.$id);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
<script lang="ts">
|
||||
import type { Invoice } from '$lib/sdk/billing';
|
||||
import { getApiEndpoint } from '$lib/stores/sdk';
|
||||
import { selectedInvoice, showRetryModal } from '../billing/store';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
@@ -14,13 +13,14 @@
|
||||
IconRefresh
|
||||
} from '@appwrite.io/pink-icons-svelte';
|
||||
import { page } from '$app/state';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
const endpoint = getApiEndpoint();
|
||||
|
||||
export let invoices: Invoice[];
|
||||
export let invoices: Models.Invoice[];
|
||||
export let showActions = true;
|
||||
|
||||
function retryPayment(invoice: Invoice) {
|
||||
function retryPayment(invoice: Models.Invoice) {
|
||||
$selectedInvoice = invoice;
|
||||
$showRetryModal = true;
|
||||
}
|
||||
|
||||
@@ -4,12 +4,7 @@
|
||||
import { BarChart, Legend } from '$lib/charts';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { bytesToSize, humanFileSize, mbSecondsToGBHours } from '$lib/helpers/sizeConvertion';
|
||||
import {
|
||||
getServiceLimit,
|
||||
showUsageRatesModal,
|
||||
type Tier,
|
||||
upgradeURL
|
||||
} from '$lib/stores/billing';
|
||||
import { getServiceLimit, showUsageRatesModal, upgradeURL } from '$lib/stores/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import ProjectBreakdown from './ProjectBreakdown.svelte';
|
||||
import { formatNum } from '$lib/helpers/string';
|
||||
@@ -25,8 +20,9 @@
|
||||
export let data;
|
||||
|
||||
const tier = data?.plan
|
||||
? (data.plan.$id as Tier)
|
||||
: (data?.currentInvoice?.plan ?? $organization?.billingPlan);
|
||||
? (data.plan.$id as BillingPlan)
|
||||
: ((data?.currentInvoice?.plan as BillingPlan) ??
|
||||
($organization?.billingPlan as BillingPlan));
|
||||
const plan = data?.plan ?? undefined;
|
||||
|
||||
$: projects = (data.organizationUsage as OrganizationUsage).projects;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import type { Invoice } from '$lib/sdk/billing';
|
||||
import { type Organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
@@ -42,18 +41,18 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
|
||||
let startDate: string = org.billingCurrentInvoiceDate;
|
||||
let endDate: string = org.billingNextInvoiceDate;
|
||||
let currentInvoice: Invoice = undefined;
|
||||
let currentInvoice: Models.Invoice = undefined;
|
||||
|
||||
if (invoice) {
|
||||
currentInvoice = await sdk.forConsole.billing.getInvoice(org.$id, invoice);
|
||||
currentInvoice = await sdk.forConsole.organizations.getInvoice(org.$id, invoice);
|
||||
startDate = currentInvoice.from;
|
||||
endDate = currentInvoice.to;
|
||||
}
|
||||
const [invoices, usage, organizationMembers, plan] = await Promise.all([
|
||||
sdk.forConsole.billing.listInvoices(org.$id, [Query.orderDesc('from')]),
|
||||
sdk.forConsole.organizations.listInvoices(org.$id, [Query.orderDesc('from')]),
|
||||
sdk.forConsole.billing.listUsage(params.organization, startDate, endDate),
|
||||
sdk.forConsole.teams.listMemberships(params.organization, [Query.limit(100)]),
|
||||
sdk.forConsole.billing.getOrganizationPlan(org.$id)
|
||||
sdk.forConsole.organizations.getPlan(org.$id)
|
||||
]);
|
||||
|
||||
const projects: { [key: string]: Models.Project } = {};
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@
|
||||
export let members: Models.MembershipList;
|
||||
|
||||
$: total = members?.total ?? 0;
|
||||
$: plan = $plansInfo?.get($organization?.billingPlan);
|
||||
$: plan = $plansInfo?.get($organization?.billingPlan as BillingPlan);
|
||||
</script>
|
||||
|
||||
<CardGrid>
|
||||
|
||||
@@ -6,16 +6,16 @@ import { preferences } from '$lib/stores/preferences';
|
||||
import { failedInvoice } from '$lib/stores/billing';
|
||||
import { isCloud } from '$lib/system';
|
||||
import { defaultRoles, defaultScopes } from '$lib/constants';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import { get } from 'svelte/store';
|
||||
import { headerAlert } from '$lib/stores/headerAlert';
|
||||
import PaymentFailed from '$lib/components/billing/alerts/paymentFailed.svelte';
|
||||
import { loadAvailableRegions } from '$routes/(console)/regions';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
depends(Dependencies.PROJECT);
|
||||
let currentPlan: Plan = null;
|
||||
let currentPlan: Models.BillingPlan = null;
|
||||
|
||||
try {
|
||||
const project = await sdk.forConsole.projects.get(params.project);
|
||||
@@ -34,8 +34,8 @@ export const load: LayoutLoad = async ({ params, depends }) => {
|
||||
let roles = isCloud ? [] : defaultRoles;
|
||||
let scopes = isCloud ? [] : defaultScopes;
|
||||
if (isCloud) {
|
||||
currentPlan = await sdk.forConsole.billing.getOrganizationPlan(project.teamId);
|
||||
const res = await sdk.forConsole.billing.getRoles(project.teamId);
|
||||
currentPlan = await sdk.forConsole.organizations.getPlan(project.teamId);
|
||||
const res = await sdk.forConsole.organizations.getScopes(project.teamId);
|
||||
roles = res.roles;
|
||||
scopes = res.scopes;
|
||||
if (scopes.includes('billing.read')) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import type { PageLoad, RouteParams } from './$types';
|
||||
import type { BackupPolicy } from '$lib/sdk/backups';
|
||||
import { isSelfHosted } from '$lib/system';
|
||||
import { isCloud } from '$lib/system';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
|
||||
export const load: PageLoad = async ({ url, route, depends, params, parent }) => {
|
||||
depends(Dependencies.DATABASES);
|
||||
@@ -45,7 +44,7 @@ async function fetchDatabasesAndBackups(
|
||||
offset: number,
|
||||
params: RouteParams,
|
||||
search?: string | undefined,
|
||||
currentPlan?: Plan
|
||||
currentPlan?: Models.BillingPlan
|
||||
) {
|
||||
const backupsEnabled = currentPlan?.backupsEnabled ?? true;
|
||||
|
||||
|
||||
+7
-1
@@ -24,9 +24,15 @@
|
||||
import { page } from '$app/state';
|
||||
import { capitalize } from '$lib/helpers/string';
|
||||
import { IconExternalLink } from '@appwrite.io/pink-icons-svelte';
|
||||
import type { BillingPlan } from '$lib/constants';
|
||||
|
||||
$: buttonDisabled =
|
||||
isCloud && isServiceLimited('functions', $organization?.billingPlan, $functionsList?.total);
|
||||
isCloud &&
|
||||
isServiceLimited(
|
||||
'functions',
|
||||
$organization?.billingPlan as BillingPlan,
|
||||
$functionsList?.total
|
||||
);
|
||||
</script>
|
||||
|
||||
<Container>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Aggregation, Invoice } from '$lib/sdk/billing';
|
||||
import type { Aggregation } from '$lib/sdk/billing';
|
||||
import { accumulateUsage } from '$lib/sdk/usage';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { Query } from '@appwrite.io/console';
|
||||
import { Query, type Models } from '@appwrite.io/console';
|
||||
import type { PageLoad } from './$types';
|
||||
|
||||
export const load: PageLoad = async ({ params, parent }) => {
|
||||
@@ -10,11 +10,11 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
|
||||
let startDate: string = organization.billingCurrentInvoiceDate;
|
||||
let endDate: string = organization.billingNextInvoiceDate;
|
||||
let currentInvoice: Invoice = undefined;
|
||||
let currentInvoice: Models.Invoice = undefined;
|
||||
let currentAggregation: Aggregation = undefined;
|
||||
|
||||
if (invoice) {
|
||||
currentInvoice = await sdk.forConsole.billing.getInvoice(organization.$id, invoice);
|
||||
currentInvoice = await sdk.forConsole.organizations.getInvoice(organization.$id, invoice);
|
||||
currentAggregation = await sdk.forConsole.billing.getAggregation(
|
||||
organization.$id,
|
||||
currentInvoice.aggregationId
|
||||
@@ -25,7 +25,7 @@ export const load: PageLoad = async ({ params, parent }) => {
|
||||
}
|
||||
|
||||
const [invoices, usage] = await Promise.all([
|
||||
sdk.forConsole.billing.listInvoices(organization.$id, [Query.orderDesc('from')]),
|
||||
sdk.forConsole.organizations.listInvoices(organization.$id, [Query.orderDesc('from')]),
|
||||
sdk.forProject(region, project).project.getUsage(startDate, endDate)
|
||||
]);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
import Table from './table.svelte';
|
||||
import { onMount } from 'svelte';
|
||||
import { invalidate } from '$app/navigation';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { BillingPlan, Dependencies } from '$lib/constants';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
export let data;
|
||||
let show = false;
|
||||
@@ -37,8 +37,11 @@
|
||||
},
|
||||
keys: ['c'],
|
||||
disabled:
|
||||
isServiceLimited('sites', $organization?.billingPlan, data.siteList?.total) ||
|
||||
!$canWriteSites,
|
||||
isServiceLimited(
|
||||
'sites',
|
||||
$organization?.billingPlan as BillingPlan,
|
||||
data.siteList?.total
|
||||
) || !$canWriteSites,
|
||||
icon: IconPlus,
|
||||
group: 'sites'
|
||||
}
|
||||
|
||||
+1
-2
@@ -9,11 +9,10 @@
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { GRACE_PERIOD_OVERRIDE, isCloud } from '$lib/system';
|
||||
import { updateBucket } from './+page.svelte';
|
||||
import type { Plan } from '$lib/sdk/billing';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export let bucket: Models.Bucket;
|
||||
export let currentPlan: Plan | null;
|
||||
export let currentPlan: Models.BillingPlan | null;
|
||||
|
||||
const service = currentPlan ? currentPlan['fileSize'] : null;
|
||||
const { value, unit, baseValue, units } = createByteUnitPair(bucket.maximumFileSize, 1000);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { HeaderAlert } from '$lib/stores/headerAlert';
|
||||
import type { Organization } from '$lib/stores/organization';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
|
||||
@@ -16,4 +15,4 @@ export const protocol = derived(page, ($page) =>
|
||||
);
|
||||
|
||||
export const activeHeaderAlert = writable<HeaderAlert>(null);
|
||||
export const orgMissingPaymentMethod = writable<Organization>(null);
|
||||
export const orgMissingPaymentMethod = writable<Models.Organization<Record<string, unknown>>>(null);
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { base } from '$app/paths';
|
||||
import type { Campaign } from '$lib/stores/campaigns';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export const load: PageLoad = async ({ url }) => {
|
||||
if (url.searchParams.has('code')) {
|
||||
const code = url.searchParams.get('code');
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
try {
|
||||
const couponData = await sdk.forConsole.billing.getCoupon(code);
|
||||
const couponData = await sdk.forConsole.console.getCoupon(code);
|
||||
if (couponData.campaign) {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
|
||||
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
|
||||
return {
|
||||
couponData,
|
||||
campaign
|
||||
@@ -23,9 +23,9 @@ export const load: PageLoad = async ({ url }) => {
|
||||
}
|
||||
if (url.searchParams.has('campaign')) {
|
||||
const campaignId = url.searchParams.get('campaign');
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
try {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
|
||||
campaign = await sdk.forConsole.console.getCampaign(campaignId);
|
||||
return { campaign };
|
||||
} catch (e) {
|
||||
redirect(303, `${base}/login`);
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { base } from '$app/paths';
|
||||
import type { Campaign } from '$lib/stores/campaigns.js';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import type { PageLoad } from './$types';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
|
||||
export const load: PageLoad = async ({ url }) => {
|
||||
if (url.searchParams.has('code')) {
|
||||
const code = url.searchParams.get('code');
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
try {
|
||||
const couponData = await sdk.forConsole.billing.getCoupon(code);
|
||||
const couponData = await sdk.forConsole.console.getCoupon(code);
|
||||
if (couponData.campaign) {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(couponData.campaign);
|
||||
campaign = await sdk.forConsole.console.getCampaign(couponData.campaign);
|
||||
return {
|
||||
couponData,
|
||||
campaign
|
||||
@@ -23,9 +23,9 @@ export const load: PageLoad = async ({ url }) => {
|
||||
}
|
||||
if (url.searchParams.has('campaign')) {
|
||||
const campaignId = url.searchParams.get('campaign');
|
||||
let campaign: Campaign;
|
||||
let campaign: Models.Campaign;
|
||||
try {
|
||||
campaign = await sdk.forConsole.billing.getCampaign(campaignId);
|
||||
campaign = await sdk.forConsole.console.getCampaign(campaignId);
|
||||
return { campaign };
|
||||
} catch (e) {
|
||||
redirect(303, `${base}/register`);
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { BillingPlan } from '$lib/constants.js';
|
||||
import { sdk } from '$lib/stores/sdk.js';
|
||||
import { ID, type Models } from '@appwrite.io/console';
|
||||
import { BillingPlan, ID, type Models } from '@appwrite.io/console';
|
||||
import { isCloud } from '$lib/system.js';
|
||||
import { error, redirect } from '@sveltejs/kit';
|
||||
import type { OrganizationList } from '$lib/stores/organization.js';
|
||||
@@ -34,16 +33,16 @@ export const load = async ({ parent, url, params }) => {
|
||||
|
||||
let organizations: Models.TeamList<Record<string, unknown>> | OrganizationList | undefined;
|
||||
if (isCloud) {
|
||||
organizations = account?.$id ? await sdk.forConsole.billing.listOrganization() : undefined;
|
||||
organizations = account?.$id ? await sdk.forConsole.organizations.list() : undefined;
|
||||
} else {
|
||||
organizations = account?.$id ? await sdk.forConsole.teams.list() : undefined;
|
||||
}
|
||||
|
||||
if (!organizations?.total && account?.$id) {
|
||||
await sdk.forConsole.billing.createOrganization(
|
||||
await sdk.forConsole.organizations.create(
|
||||
ID.unique(),
|
||||
'Personal project',
|
||||
BillingPlan.FREE,
|
||||
BillingPlan.Tier0,
|
||||
null,
|
||||
null
|
||||
);
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
|
||||
if (page.url.searchParams.has('code')) {
|
||||
const code = page.url.searchParams.get('code');
|
||||
const coupon = await sdk.forConsole.billing.getCoupon(code).catch<null>(() => null);
|
||||
const coupon = await sdk.forConsole.console.getCoupon(code).catch<null>(() => null);
|
||||
if (coupon?.campaign) {
|
||||
const campaign = await sdk.forConsole.billing
|
||||
.getCampaign(coupon.campaign)
|
||||
|
||||
@@ -32,7 +32,7 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
|
||||
account: account,
|
||||
organizations: !isCloud
|
||||
? await sdk.forConsole.teams.list()
|
||||
: await sdk.forConsole.billing.listOrganization()
|
||||
: await sdk.forConsole.organizations.list()
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user