/** * Platform API * API functions for platform-level operations (businesses, users, etc.) */ import apiClient from './client'; export interface PlatformBusinessOwner { id: number; username: string; full_name: string; email: string; role: string; email_verified: boolean; } export interface PlatformBusiness { id: number; name: string; subdomain: string; tier: string; is_active: boolean; created_on: string; user_count: number; owner: PlatformBusinessOwner | null; max_users: number; max_resources: number; contact_email?: string; phone?: string; // Platform permissions can_manage_oauth_credentials: boolean; can_accept_payments: boolean; can_use_custom_domain: boolean; can_white_label: boolean; can_api_access: boolean; // Feature permissions (optional - returned by API but may not always be present in tests) can_add_video_conferencing?: boolean; can_connect_to_api?: boolean; can_book_repeated_events?: boolean; can_require_2fa?: boolean; can_download_logs?: boolean; can_delete_data?: boolean; can_use_sms_reminders?: boolean; can_use_masked_phone_numbers?: boolean; can_use_pos?: boolean; can_use_mobile_app?: boolean; can_export_data?: boolean; can_use_plugins?: boolean; can_use_tasks?: boolean; can_create_plugins?: boolean; can_use_webhooks?: boolean; can_use_calendar_sync?: boolean; can_use_contracts?: boolean; } export interface PlatformBusinessUpdate { name?: string; is_active?: boolean; subscription_tier?: string; max_users?: number; max_resources?: number; // Platform permissions can_manage_oauth_credentials?: boolean; can_accept_payments?: boolean; can_use_custom_domain?: boolean; can_white_label?: boolean; can_api_access?: boolean; // Feature permissions can_add_video_conferencing?: boolean; can_connect_to_api?: boolean; can_book_repeated_events?: boolean; can_require_2fa?: boolean; can_download_logs?: boolean; can_delete_data?: boolean; can_use_sms_reminders?: boolean; can_use_masked_phone_numbers?: boolean; can_use_pos?: boolean; can_use_mobile_app?: boolean; can_export_data?: boolean; can_use_plugins?: boolean; can_use_tasks?: boolean; can_create_plugins?: boolean; can_use_webhooks?: boolean; can_use_calendar_sync?: boolean; can_use_contracts?: boolean; can_process_refunds?: boolean; can_create_packages?: boolean; can_use_email_templates?: boolean; can_customize_booking_page?: boolean; advanced_reporting?: boolean; priority_support?: boolean; dedicated_support?: boolean; sso_enabled?: boolean; } export interface PlatformBusinessCreate { name: string; subdomain: string; subscription_tier?: string; is_active?: boolean; max_users?: number; max_resources?: number; contact_email?: string; phone?: string; can_manage_oauth_credentials?: boolean; // Owner details (optional) owner_email?: string; owner_name?: string; owner_password?: string; } export interface PlatformUser { id: number; email: string; username: string; name?: string; role?: string; is_active: boolean; is_staff: boolean; is_superuser: boolean; email_verified: boolean; business: number | null; business_name?: string; business_subdomain?: string; date_joined: string; last_login?: string; } /** * Get all businesses (platform admin only) */ export const getBusinesses = async (): Promise => { const response = await apiClient.get('/platform/businesses/'); return response.data; }; /** * Update a business (platform admin only) */ export const updateBusiness = async ( businessId: number, data: PlatformBusinessUpdate ): Promise => { const response = await apiClient.patch( `/platform/businesses/${businessId}/`, data ); return response.data; }; /** * Create a new business (platform admin only) */ export const createBusiness = async ( data: PlatformBusinessCreate ): Promise => { const response = await apiClient.post( '/platform/businesses/', data ); return response.data; }; /** * Delete a business/tenant (platform admin only) * This permanently deletes the tenant and all associated data */ export const deleteBusiness = async (businessId: number): Promise => { await apiClient.delete(`/platform/businesses/${businessId}/`); }; /** * Get all users (platform admin only) */ export const getUsers = async (): Promise => { const response = await apiClient.get('/platform/users/'); return response.data; }; /** * Get users for a specific business */ export const getBusinessUsers = async (businessId: number): Promise => { const response = await apiClient.get(`/platform/users/?business=${businessId}`); return response.data; }; /** * Verify a user's email (platform admin only) */ export const verifyUserEmail = async (userId: number): Promise => { await apiClient.post(`/platform/users/${userId}/verify_email/`); }; // ============================================================================ // Tenant Invitations // ============================================================================ export interface TenantInvitation { id: number; email: string; token: string; status: 'PENDING' | 'ACCEPTED' | 'EXPIRED' | 'CANCELLED'; suggested_business_name: string; subscription_tier: 'FREE' | 'STARTER' | 'PROFESSIONAL' | 'ENTERPRISE'; custom_max_users: number | null; custom_max_resources: number | null; permissions: { can_manage_oauth_credentials?: boolean; can_accept_payments?: boolean; can_use_custom_domain?: boolean; can_white_label?: boolean; can_api_access?: boolean; }; personal_message: string; invited_by: number; invited_by_email: string; created_at: string; expires_at: string; accepted_at: string | null; created_tenant: number | null; created_tenant_name: string | null; created_user: number | null; created_user_email: string | null; } export interface TenantInvitationCreate { email: string; suggested_business_name?: string; subscription_tier: 'FREE' | 'STARTER' | 'PROFESSIONAL' | 'ENTERPRISE'; custom_max_users?: number | null; custom_max_resources?: number | null; permissions?: { can_manage_oauth_credentials?: boolean; can_accept_payments?: boolean; can_use_custom_domain?: boolean; can_white_label?: boolean; can_api_access?: boolean; }; personal_message?: string; } export interface TenantInvitationDetail { email: string; suggested_business_name: string; subscription_tier: string; effective_max_users: number; effective_max_resources: number; permissions: { can_manage_oauth_credentials?: boolean; can_accept_payments?: boolean; can_use_custom_domain?: boolean; can_white_label?: boolean; can_api_access?: boolean; }; expires_at: string; } export interface TenantInvitationAccept { email: string; password: string; first_name: string; last_name: string; business_name: string; subdomain: string; contact_email?: string; phone?: string; } /** * Get all tenant invitations (platform admin only) */ export const getTenantInvitations = async (): Promise => { const response = await apiClient.get('/platform/tenant-invitations/'); return response.data; }; /** * Create a tenant invitation (platform admin only) */ export const createTenantInvitation = async ( data: TenantInvitationCreate ): Promise => { const response = await apiClient.post( '/platform/tenant-invitations/', data ); return response.data; }; /** * Resend a tenant invitation (platform admin only) */ export const resendTenantInvitation = async (invitationId: number): Promise => { await apiClient.post(`/platform/tenant-invitations/${invitationId}/resend/`); }; /** * Cancel a tenant invitation (platform admin only) */ export const cancelTenantInvitation = async (invitationId: number): Promise => { await apiClient.post(`/platform/tenant-invitations/${invitationId}/cancel/`); }; /** * Get invitation details by token (public, no auth required) */ export const getInvitationByToken = async (token: string): Promise => { const response = await apiClient.get( `/platform/tenant-invitations/token/${token}/` ); return response.data; }; /** * Accept an invitation by token (public, no auth required) */ export const acceptInvitation = async ( token: string, data: TenantInvitationAccept ): Promise<{ detail: string }> => { const response = await apiClient.post<{ detail: string }>( `/platform/tenant-invitations/token/${token}/accept/`, data ); return response.data; };