Add new frontend - fix 11
This commit is contained in:
369
frontend/src/api/services/tenantService.ts
Normal file
369
frontend/src/api/services/tenantService.ts
Normal file
@@ -0,0 +1,369 @@
|
||||
// src/api/services/TenantService.ts
|
||||
import { apiClient } from '../base/apiClient';
|
||||
import {
|
||||
ApiResponse,
|
||||
TenantInfo,
|
||||
} from '../types/api';
|
||||
|
||||
export interface TenantCreate {
|
||||
name: string;
|
||||
email: string;
|
||||
phone: string;
|
||||
address: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
business_type: 'individual_bakery' | 'central_workshop';
|
||||
subscription_plan?: string;
|
||||
settings?: Record<string, any>;
|
||||
}
|
||||
|
||||
export interface TenantUpdate extends Partial<TenantCreate> {
|
||||
is_active?: boolean;
|
||||
}
|
||||
|
||||
export interface TenantSettings {
|
||||
business_hours: {
|
||||
monday: { open: string; close: string; closed: boolean };
|
||||
tuesday: { open: string; close: string; closed: boolean };
|
||||
wednesday: { open: string; close: string; closed: boolean };
|
||||
thursday: { open: string; close: string; closed: boolean };
|
||||
friday: { open: string; close: string; closed: boolean };
|
||||
saturday: { open: string; close: string; closed: boolean };
|
||||
sunday: { open: string; close: string; closed: boolean };
|
||||
};
|
||||
timezone: string;
|
||||
currency: string;
|
||||
language: string;
|
||||
notification_preferences: {
|
||||
email_enabled: boolean;
|
||||
whatsapp_enabled: boolean;
|
||||
forecast_alerts: boolean;
|
||||
training_notifications: boolean;
|
||||
weekly_reports: boolean;
|
||||
};
|
||||
forecast_preferences: {
|
||||
default_forecast_days: number;
|
||||
confidence_level: number;
|
||||
include_weather: boolean;
|
||||
include_traffic: boolean;
|
||||
alert_thresholds: {
|
||||
high_demand_increase: number;
|
||||
low_demand_decrease: number;
|
||||
};
|
||||
};
|
||||
data_retention_days: number;
|
||||
}
|
||||
|
||||
export interface TenantStats {
|
||||
total_users: number;
|
||||
active_users: number;
|
||||
total_sales_records: number;
|
||||
total_forecasts: number;
|
||||
total_notifications_sent: number;
|
||||
storage_used_mb: number;
|
||||
api_calls_this_month: number;
|
||||
last_activity: string;
|
||||
subscription_status: 'active' | 'inactive' | 'suspended';
|
||||
subscription_expires: string;
|
||||
}
|
||||
|
||||
export interface TenantUser {
|
||||
id: string;
|
||||
email: string;
|
||||
full_name: string;
|
||||
role: string;
|
||||
is_active: boolean;
|
||||
last_login: string | null;
|
||||
created_at: string;
|
||||
}
|
||||
|
||||
export interface InviteUser {
|
||||
email: string;
|
||||
role: 'admin' | 'manager' | 'user';
|
||||
full_name?: string;
|
||||
send_invitation_email?: boolean;
|
||||
}
|
||||
|
||||
export class TenantService {
|
||||
/**
|
||||
* Get current tenant info
|
||||
*/
|
||||
async getCurrentTenant(): Promise<TenantInfo> {
|
||||
const response = await apiClient.get<ApiResponse<TenantInfo>>('/tenants/current');
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update current tenant
|
||||
*/
|
||||
async updateCurrentTenant(updates: TenantUpdate): Promise<TenantInfo> {
|
||||
const response = await apiClient.put<ApiResponse<TenantInfo>>('/tenants/current', updates);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tenant settings
|
||||
*/
|
||||
async getTenantSettings(): Promise<TenantSettings> {
|
||||
const response = await apiClient.get<ApiResponse<TenantSettings>>('/tenants/settings');
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tenant settings
|
||||
*/
|
||||
async updateTenantSettings(settings: Partial<TenantSettings>): Promise<TenantSettings> {
|
||||
const response = await apiClient.put<ApiResponse<TenantSettings>>(
|
||||
'/tenants/settings',
|
||||
settings
|
||||
);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tenant statistics
|
||||
*/
|
||||
async getTenantStats(): Promise<TenantStats> {
|
||||
const response = await apiClient.get<ApiResponse<TenantStats>>('/tenants/stats');
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tenant users
|
||||
*/
|
||||
async getTenantUsers(params?: {
|
||||
role?: string;
|
||||
active?: boolean;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}): Promise<{
|
||||
users: TenantUser[];
|
||||
total: number;
|
||||
page: number;
|
||||
pages: number;
|
||||
}> {
|
||||
const response = await apiClient.get<ApiResponse<any>>('/tenants/users', { params });
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invite user to tenant
|
||||
*/
|
||||
async inviteUser(invitation: InviteUser): Promise<{
|
||||
invitation_id: string;
|
||||
email: string;
|
||||
role: string;
|
||||
expires_at: string;
|
||||
invitation_token: string;
|
||||
}> {
|
||||
const response = await apiClient.post<ApiResponse<any>>('/tenants/users/invite', invitation);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update user role
|
||||
*/
|
||||
async updateUserRole(userId: string, role: string): Promise<TenantUser> {
|
||||
const response = await apiClient.patch<ApiResponse<TenantUser>>(
|
||||
`/tenants/users/${userId}`,
|
||||
{ role }
|
||||
);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deactivate user
|
||||
*/
|
||||
async deactivateUser(userId: string): Promise<TenantUser> {
|
||||
const response = await apiClient.patch<ApiResponse<TenantUser>>(
|
||||
`/tenants/users/${userId}`,
|
||||
{ is_active: false }
|
||||
);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactivate user
|
||||
*/
|
||||
async reactivateUser(userId: string): Promise<TenantUser> {
|
||||
const response = await apiClient.patch<ApiResponse<TenantUser>>(
|
||||
`/tenants/users/${userId}`,
|
||||
{ is_active: true }
|
||||
);
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove user from tenant
|
||||
*/
|
||||
async removeUser(userId: string): Promise<void> {
|
||||
await apiClient.delete(`/tenants/users/${userId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pending invitations
|
||||
*/
|
||||
async getPendingInvitations(): Promise<{
|
||||
id: string;
|
||||
email: string;
|
||||
role: string;
|
||||
invited_at: string;
|
||||
expires_at: string;
|
||||
invited_by: string;
|
||||
}[]> {
|
||||
const response = await apiClient.get<ApiResponse<any>>('/tenants/invitations');
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel invitation
|
||||
*/
|
||||
async cancelInvitation(invitationId: string): Promise<void> {
|
||||
await apiClient.delete(`/tenants/invitations/${invitationId}`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resend invitation
|
||||
*/
|
||||
async resendInvitation(invitationId: string): Promise<void> {
|
||||
await apiClient.post(`/tenants/invitations/${invitationId}/resend`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tenant activity log
|
||||
*/
|
||||
async getActivityLog(params?: {
|
||||
userId?: string;
|
||||
action?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
page?: number;
|
||||
limit?: number;
|
||||
}): Promise<{
|
||||
activities: {
|
||||
id: string;
|
||||
user_id: string;
|
||||
user_name: string;
|
||||
action: string;
|
||||
resource: string;
|
||||
resource_id: string;
|
||||
details?: Record<string, any>;
|
||||
ip_address?: string;
|
||||
user_agent?: string;
|
||||
created_at: string;
|
||||
}[];
|
||||
total: number;
|
||||
page: number;
|
||||
pages: number;
|
||||
}> {
|
||||
const response = await apiClient.get<ApiResponse<any>>('/tenants/activity', { params });
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get tenant billing info
|
||||
*/
|
||||
async getBillingInfo(): Promise<{
|
||||
subscription_plan: string;
|
||||
billing_cycle: 'monthly' | 'yearly';
|
||||
next_billing_date: string;
|
||||
amount: number;
|
||||
currency: string;
|
||||
payment_method: {
|
||||
type: string;
|
||||
last_four: string;
|
||||
expires: string;
|
||||
};
|
||||
usage: {
|
||||
api_calls: number;
|
||||
storage_mb: number;
|
||||
users: number;
|
||||
limits: {
|
||||
api_calls_per_month: number;
|
||||
storage_mb: number;
|
||||
max_users: number;
|
||||
};
|
||||
};
|
||||
}> {
|
||||
const response = await apiClient.get<ApiResponse<any>>('/tenants/billing');
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update billing info
|
||||
*/
|
||||
async updateBillingInfo(billingData: {
|
||||
payment_method_token?: string;
|
||||
billing_address?: {
|
||||
street: string;
|
||||
city: string;
|
||||
state: string;
|
||||
zip: string;
|
||||
country: string;
|
||||
};
|
||||
}): Promise<void> {
|
||||
await apiClient.put('/tenants/billing', billingData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change subscription plan
|
||||
*/
|
||||
async changeSubscriptionPlan(
|
||||
planId: string,
|
||||
billingCycle: 'monthly' | 'yearly'
|
||||
): Promise<{
|
||||
subscription_id: string;
|
||||
plan: string;
|
||||
billing_cycle: string;
|
||||
next_billing_date: string;
|
||||
proration_amount?: number;
|
||||
}> {
|
||||
const response = await apiClient.post<ApiResponse<any>>('/tenants/subscription/change', {
|
||||
plan_id: planId,
|
||||
billing_cycle: billingCycle,
|
||||
});
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel subscription
|
||||
*/
|
||||
async cancelSubscription(cancelAt: 'immediately' | 'end_of_period'): Promise<{
|
||||
cancelled_at: string;
|
||||
will_cancel_at: string;
|
||||
refund_amount?: number;
|
||||
}> {
|
||||
const response = await apiClient.post<ApiResponse<any>>('/tenants/subscription/cancel', {
|
||||
cancel_at: cancelAt,
|
||||
});
|
||||
return response.data!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Export tenant data
|
||||
*/
|
||||
async exportTenantData(dataTypes: string[], format: 'json' | 'csv'): Promise<Blob> {
|
||||
const response = await apiClient.post('/tenants/export', {
|
||||
data_types: dataTypes,
|
||||
format,
|
||||
responseType: 'blob',
|
||||
});
|
||||
return response as unknown as Blob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete tenant (GDPR compliance)
|
||||
*/
|
||||
async deleteTenant(confirmationToken: string): Promise<{
|
||||
deletion_scheduled_at: string;
|
||||
data_retention_until: string;
|
||||
recovery_period_days: number;
|
||||
}> {
|
||||
const response = await apiClient.delete<ApiResponse<any>>('/tenants/current', {
|
||||
data: { confirmation_token: confirmationToken },
|
||||
});
|
||||
return response.data!;
|
||||
}
|
||||
}
|
||||
|
||||
export const tenantService = new TenantService();
|
||||
Reference in New Issue
Block a user