* Fix: fix accounts view, menu * add migration * add application_role to account-related fields
318 lines
6.9 KiB
TypeScript
318 lines
6.9 KiB
TypeScript
import { SupabaseClient } from '@supabase/supabase-js';
|
|
|
|
import { Database } from '@kit/supabase/database';
|
|
|
|
import { UpdateHealthBenefitData } from './types';
|
|
|
|
/**
|
|
* Class representing an API for interacting with team accounts.
|
|
* @constructor
|
|
* @param {SupabaseClient<Database>} client - The Supabase client instance.
|
|
*/
|
|
export class TeamAccountsApi {
|
|
constructor(private readonly client: SupabaseClient<Database>) {}
|
|
|
|
/**
|
|
* @name getTeamAccount
|
|
* @description Get the account data for the given slug.
|
|
* @param slug
|
|
*/
|
|
async getTeamAccount(slug: string) {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts')
|
|
.select('*')
|
|
.eq('slug', slug)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @name getTeamAccountById
|
|
* @description Check if the user is already in the account.
|
|
* @param accountId
|
|
*/
|
|
async getTeamAccountById(accountId: string) {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts')
|
|
.select('*')
|
|
.eq('id', accountId)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @name getSubscription
|
|
* @description Get the subscription data for the account.
|
|
* @param accountId
|
|
*/
|
|
async getSubscription(accountId: string) {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('subscriptions')
|
|
.select('*, items: subscription_items !inner (*)')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* Get the orders data for the given account.
|
|
* @param accountId
|
|
*/
|
|
async getOrder(accountId: string) {
|
|
const response = await this.client
|
|
.schema('medreport')
|
|
.from('orders')
|
|
.select('*, items: order_items !inner (*)')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (response.error) {
|
|
throw response.error;
|
|
}
|
|
|
|
return response.data;
|
|
}
|
|
|
|
/**
|
|
* @name getAccountWorkspace
|
|
* @description Get the account workspace data.
|
|
* @param slug
|
|
*/
|
|
async getAccountWorkspace(slug: string, userId: string) {
|
|
const accountPromise = this.client
|
|
.schema('medreport')
|
|
.rpc('team_account_workspace', {
|
|
account_slug: slug,
|
|
});
|
|
|
|
const accountsPromise = this.client
|
|
.schema('medreport')
|
|
.from('accounts_memberships')
|
|
.select(
|
|
`
|
|
account_id,
|
|
user_accounts (
|
|
id,
|
|
role,
|
|
name,
|
|
slug,
|
|
picture_url,
|
|
application_role
|
|
)
|
|
`,
|
|
)
|
|
.eq('user_id', userId)
|
|
.eq('account_role', 'owner');
|
|
|
|
const [accountResult, accountsResult] = await Promise.all([
|
|
accountPromise,
|
|
accountsPromise,
|
|
]);
|
|
|
|
if (accountResult.error) {
|
|
return {
|
|
error: accountResult.error,
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
if (accountsResult.error) {
|
|
return {
|
|
error: accountsResult.error,
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
const accountData = accountResult.data[0];
|
|
|
|
if (!accountData) {
|
|
return {
|
|
error: new Error('Account data not found'),
|
|
data: null,
|
|
};
|
|
}
|
|
|
|
return {
|
|
data: {
|
|
account: accountData,
|
|
accounts: accountsResult.data,
|
|
},
|
|
error: null,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @name hasPermission
|
|
* @description Check if the user has permission to manage billing for the account.
|
|
*/
|
|
async hasPermission(params: {
|
|
accountId: string;
|
|
userId: string;
|
|
permission: Database['medreport']['Enums']['app_permissions'];
|
|
}) {
|
|
const { data, error } = await this.client.rpc('has_permission', {
|
|
account_id: params.accountId,
|
|
user_id: params.userId,
|
|
permission_name: params.permission,
|
|
});
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/**
|
|
* @name getMembersCount
|
|
* @description Get the number of members in the account.
|
|
* @param accountId
|
|
*/
|
|
async getMembersCount(accountId: string) {
|
|
const { count, error } = await this.client
|
|
.schema('medreport')
|
|
.from('accounts_memberships')
|
|
.select('*', {
|
|
head: true,
|
|
count: 'exact',
|
|
})
|
|
.eq('account_id', accountId);
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return count;
|
|
}
|
|
|
|
/**
|
|
* @name getCustomerId
|
|
* @description Get the billing customer ID for the given account.
|
|
* @param accountId
|
|
*/
|
|
async getCustomerId(accountId: string) {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('billing_customers')
|
|
.select('customer_id')
|
|
.eq('account_id', accountId)
|
|
.maybeSingle();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data?.customer_id;
|
|
}
|
|
|
|
/**
|
|
* @name getInvitation
|
|
* @description Get the invitation data from the invite token.
|
|
* @param adminClient - The admin client instance. Since the user is not yet part of the account, we need to use an admin client to read the pending membership
|
|
* @param token - The invitation token.
|
|
*/
|
|
async getInvitation(adminClient: SupabaseClient<Database>, token: string) {
|
|
const { data: invitation, error } = await adminClient
|
|
.schema('medreport')
|
|
.from('invitations')
|
|
.select<
|
|
string,
|
|
{
|
|
id: string;
|
|
account: {
|
|
id: string;
|
|
name: string;
|
|
slug: string;
|
|
picture_url: string;
|
|
};
|
|
}
|
|
>(
|
|
'id, expires_at, account: account_id !inner (id, name, slug, picture_url)',
|
|
)
|
|
.eq('invite_token', token)
|
|
.gte('expires_at', new Date().toISOString())
|
|
.single();
|
|
|
|
if (error ?? !invitation) {
|
|
return null;
|
|
}
|
|
|
|
return invitation;
|
|
}
|
|
|
|
/**
|
|
* @name updateHealthBenefit
|
|
* @description Update health benefits for the team account
|
|
*/
|
|
async updateHealthBenefit(data: UpdateHealthBenefitData) {
|
|
const { error } = await this.client
|
|
.schema('medreport')
|
|
.from('company_params')
|
|
.update({
|
|
benefit_occurance: data.occurance,
|
|
benefit_amount: data.amount,
|
|
updated_at: new Date().toISOString(),
|
|
})
|
|
.eq('account_id', data.accountId);
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @name getTeamAccountParams
|
|
* @description Get health benefits for the team account
|
|
*/
|
|
async getTeamAccountParams(accountId: string) {
|
|
const { data, error } = await this.client
|
|
.schema('medreport')
|
|
.from('company_params')
|
|
.select('*')
|
|
.eq('account_id', accountId)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
async getMembers(accountSlug: string) {
|
|
const members = await this.client
|
|
.schema('medreport')
|
|
.rpc('get_account_members', {
|
|
account_slug: accountSlug,
|
|
});
|
|
|
|
if (members.error) {
|
|
throw members.error;
|
|
}
|
|
|
|
return members.data;
|
|
}
|
|
}
|
|
|
|
export function createTeamAccountsApi(client: SupabaseClient<Database>) {
|
|
return new TeamAccountsApi(client);
|
|
}
|