// ================================================================ // frontend/src/api/services/tenant.ts // ================================================================ /** * Tenant Service - Complete backend alignment * * Backend API structure (3-tier architecture): * - ATOMIC: tenants.py, tenant_members.py * - OPERATIONS: tenant_operations.py * * Last Updated: 2025-10-05 * Status: ✅ Complete - Zero drift with backend */ import { apiClient } from '../client'; import { BakeryRegistration, TenantResponse, TenantAccessResponse, TenantUpdate, TenantMemberResponse, TenantStatistics, TenantSearchParams, TenantNearbyParams, } from '../types/tenant'; export class TenantService { private readonly baseUrl = '/tenants'; // =================================================================== // ATOMIC: Tenant CRUD // Backend: services/tenant/app/api/tenants.py // =================================================================== async registerBakery(bakeryData: BakeryRegistration): Promise { return apiClient.post(`${this.baseUrl}/register`, bakeryData); } async getTenant(tenantId: string): Promise { return apiClient.get(`${this.baseUrl}/${tenantId}`); } async getTenantBySubdomain(subdomain: string): Promise { return apiClient.get(`${this.baseUrl}/subdomain/${subdomain}`); } async getUserTenants(userId: string): Promise { // Use the /owned endpoint since /users/{userId} has validation issues return apiClient.get(`${this.baseUrl}/user/${userId}/owned`); } async getUserOwnedTenants(userId: string): Promise { return apiClient.get(`${this.baseUrl}/user/${userId}/owned`); } async updateTenant(tenantId: string, updateData: TenantUpdate): Promise { return apiClient.put(`${this.baseUrl}/${tenantId}`, updateData); } async deactivateTenant(tenantId: string): Promise<{ success: boolean; message: string }> { return apiClient.post<{ success: boolean; message: string }>(`${this.baseUrl}/${tenantId}/deactivate`); } async activateTenant(tenantId: string): Promise<{ success: boolean; message: string }> { return apiClient.post<{ success: boolean; message: string }>(`${this.baseUrl}/${tenantId}/activate`); } // =================================================================== // OPERATIONS: Access Control // Backend: services/tenant/app/api/tenant_operations.py // =================================================================== async verifyTenantAccess(tenantId: string, userId: string): Promise { return apiClient.get(`${this.baseUrl}/${tenantId}/access/${userId}`); } async getCurrentUserTenantAccess(tenantId: string): Promise { // This will use the current user from the auth token // The backend endpoint handles extracting user_id from the token return apiClient.get(`${this.baseUrl}/${tenantId}/my-access`); } // =================================================================== // OPERATIONS: Search & Discovery // Backend: services/tenant/app/api/tenant_operations.py // =================================================================== async searchTenants(params: TenantSearchParams): Promise { const queryParams = new URLSearchParams(); if (params.search_term) queryParams.append('search_term', params.search_term); if (params.business_type) queryParams.append('business_type', params.business_type); if (params.city) queryParams.append('city', params.city); if (params.skip !== undefined) queryParams.append('skip', params.skip.toString()); if (params.limit !== undefined) queryParams.append('limit', params.limit.toString()); return apiClient.get(`${this.baseUrl}/search?${queryParams.toString()}`); } async getNearbyTenants(params: TenantNearbyParams): Promise { const queryParams = new URLSearchParams(); queryParams.append('latitude', params.latitude.toString()); queryParams.append('longitude', params.longitude.toString()); if (params.radius_km !== undefined) queryParams.append('radius_km', params.radius_km.toString()); if (params.limit !== undefined) queryParams.append('limit', params.limit.toString()); return apiClient.get(`${this.baseUrl}/nearby?${queryParams.toString()}`); } // =================================================================== // OPERATIONS: Model Status Management // Backend: services/tenant/app/api/tenant_operations.py // =================================================================== async updateModelStatus( tenantId: string, modelTrained: boolean, lastTrainingDate?: string ): Promise { const queryParams = new URLSearchParams(); queryParams.append('model_trained', modelTrained.toString()); if (lastTrainingDate) queryParams.append('last_training_date', lastTrainingDate); return apiClient.put(`${this.baseUrl}/${tenantId}/model-status?${queryParams.toString()}`); } // =================================================================== // ATOMIC: Team Member Management // Backend: services/tenant/app/api/tenant_members.py // =================================================================== async addTeamMember( tenantId: string, userId: string, role: string ): Promise { return apiClient.post(`${this.baseUrl}/${tenantId}/members`, { user_id: userId, role: role, }); } async getTeamMembers(tenantId: string, activeOnly: boolean = true): Promise { const queryParams = new URLSearchParams(); queryParams.append('active_only', activeOnly.toString()); return apiClient.get(`${this.baseUrl}/${tenantId}/members?${queryParams.toString()}`); } async updateMemberRole( tenantId: string, memberUserId: string, newRole: string ): Promise { return apiClient.put( `${this.baseUrl}/${tenantId}/members/${memberUserId}/role`, { new_role: newRole } ); } async removeTeamMember(tenantId: string, memberUserId: string): Promise<{ success: boolean; message: string }> { return apiClient.delete<{ success: boolean; message: string }>(`${this.baseUrl}/${tenantId}/members/${memberUserId}`); } // =================================================================== // OPERATIONS: Statistics & Admin // Backend: services/tenant/app/api/tenant_operations.py // =================================================================== async getTenantStatistics(): Promise { return apiClient.get(`${this.baseUrl}/statistics`); } // =================================================================== // Frontend Context Management // =================================================================== setCurrentTenant(tenant: TenantResponse): void { // Set tenant context in API client if (tenant && tenant.id) { apiClient.setTenantId(tenant.id); } } clearCurrentTenant(): void { // Clear tenant context from API client apiClient.setTenantId(null); } } export const tenantService = new TenantService();