Improve the frontend and repository layer
This commit is contained in:
@@ -280,9 +280,7 @@ export const usePOSTransaction = (
|
||||
tenant_id: string;
|
||||
transaction_id: string;
|
||||
},
|
||||
options?: Omit<UseQueryOptions<{
|
||||
transaction: POSTransaction;
|
||||
}, ApiError>, 'queryKey' | 'queryFn'>
|
||||
options?: Omit<UseQueryOptions<POSTransaction, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: posKeys.transaction(params.tenant_id, params.transaction_id),
|
||||
@@ -293,6 +291,40 @@ export const usePOSTransaction = (
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Get POS transactions dashboard summary
|
||||
*/
|
||||
export const usePOSTransactionsDashboard = (
|
||||
params: {
|
||||
tenant_id: string;
|
||||
},
|
||||
options?: Omit<UseQueryOptions<{
|
||||
total_transactions_today: number;
|
||||
total_transactions_this_week: number;
|
||||
total_transactions_this_month: number;
|
||||
revenue_today: number;
|
||||
revenue_this_week: number;
|
||||
revenue_this_month: number;
|
||||
average_transaction_value: number;
|
||||
status_breakdown: Record<string, number>;
|
||||
payment_method_breakdown: Record<string, number>;
|
||||
sync_status: {
|
||||
synced: number;
|
||||
pending: number;
|
||||
failed: number;
|
||||
last_sync_at?: string;
|
||||
};
|
||||
}, ApiError>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: [...posKeys.transactions(), 'dashboard', params.tenant_id],
|
||||
queryFn: () => posService.getPOSTransactionsDashboard(params),
|
||||
enabled: !!params.tenant_id,
|
||||
staleTime: 30 * 1000, // 30 seconds
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// SYNC OPERATIONS
|
||||
// ============================================================================
|
||||
|
||||
140
frontend/src/api/hooks/settings.ts
Normal file
140
frontend/src/api/hooks/settings.ts
Normal file
@@ -0,0 +1,140 @@
|
||||
// frontend/src/api/hooks/settings.ts
|
||||
/**
|
||||
* React Query hooks for Tenant Settings
|
||||
* Provides data fetching, caching, and mutation hooks
|
||||
*/
|
||||
|
||||
import { useQuery, useMutation, useQueryClient, UseQueryOptions } from '@tanstack/react-query';
|
||||
import { settingsApi } from '../services/settings';
|
||||
import { useToast } from '../../hooks/ui/useToast';
|
||||
import type {
|
||||
TenantSettings,
|
||||
TenantSettingsUpdate,
|
||||
SettingsCategory,
|
||||
CategoryResetResponse,
|
||||
} from '../types/settings';
|
||||
|
||||
// Query keys
|
||||
export const settingsKeys = {
|
||||
all: ['settings'] as const,
|
||||
tenant: (tenantId: string) => ['settings', tenantId] as const,
|
||||
category: (tenantId: string, category: SettingsCategory) =>
|
||||
['settings', tenantId, category] as const,
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch all settings for a tenant
|
||||
*/
|
||||
export const useSettings = (
|
||||
tenantId: string,
|
||||
options?: Omit<UseQueryOptions<TenantSettings, Error>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<TenantSettings, Error>({
|
||||
queryKey: settingsKeys.tenant(tenantId),
|
||||
queryFn: () => settingsApi.getSettings(tenantId),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to fetch settings for a specific category
|
||||
*/
|
||||
export const useCategorySettings = (
|
||||
tenantId: string,
|
||||
category: SettingsCategory,
|
||||
options?: Omit<UseQueryOptions<Record<string, any>, Error>, 'queryKey' | 'queryFn'>
|
||||
) => {
|
||||
return useQuery<Record<string, any>, Error>({
|
||||
queryKey: settingsKeys.category(tenantId, category),
|
||||
queryFn: () => settingsApi.getCategorySettings(tenantId, category),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
...options,
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to update tenant settings
|
||||
*/
|
||||
export const useUpdateSettings = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation<
|
||||
TenantSettings,
|
||||
Error,
|
||||
{ tenantId: string; updates: TenantSettingsUpdate }
|
||||
>({
|
||||
mutationFn: ({ tenantId, updates }) => settingsApi.updateSettings(tenantId, updates),
|
||||
onSuccess: (data, variables) => {
|
||||
// Invalidate all settings queries for this tenant
|
||||
queryClient.invalidateQueries({ queryKey: settingsKeys.tenant(variables.tenantId) });
|
||||
addToast('Ajustes guardados correctamente', { type: 'success' });
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Failed to update settings:', error);
|
||||
addToast('Error al guardar los ajustes', { type: 'error' });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to update a specific category
|
||||
*/
|
||||
export const useUpdateCategorySettings = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation<
|
||||
TenantSettings,
|
||||
Error,
|
||||
{ tenantId: string; category: SettingsCategory; settings: Record<string, any> }
|
||||
>({
|
||||
mutationFn: ({ tenantId, category, settings }) =>
|
||||
settingsApi.updateCategorySettings(tenantId, category, settings),
|
||||
onSuccess: (data, variables) => {
|
||||
// Invalidate all settings queries for this tenant
|
||||
queryClient.invalidateQueries({ queryKey: settingsKeys.tenant(variables.tenantId) });
|
||||
// Also invalidate the specific category query
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: settingsKeys.category(variables.tenantId, variables.category),
|
||||
});
|
||||
addToast('Ajustes de categoría guardados correctamente', { type: 'success' });
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Failed to update category settings:', error);
|
||||
addToast('Error al guardar los ajustes de categoría', { type: 'error' });
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to reset a category to defaults
|
||||
*/
|
||||
export const useResetCategory = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const { addToast } = useToast();
|
||||
|
||||
return useMutation<
|
||||
CategoryResetResponse,
|
||||
Error,
|
||||
{ tenantId: string; category: SettingsCategory }
|
||||
>({
|
||||
mutationFn: ({ tenantId, category }) => settingsApi.resetCategory(tenantId, category),
|
||||
onSuccess: (data, variables) => {
|
||||
// Invalidate all settings queries for this tenant
|
||||
queryClient.invalidateQueries({ queryKey: settingsKeys.tenant(variables.tenantId) });
|
||||
// Also invalidate the specific category query
|
||||
queryClient.invalidateQueries({
|
||||
queryKey: settingsKeys.category(variables.tenantId, variables.category),
|
||||
});
|
||||
addToast(`Categoría '${variables.category}' restablecida a valores predeterminados`, {
|
||||
type: 'success',
|
||||
});
|
||||
},
|
||||
onError: (error) => {
|
||||
console.error('Failed to reset category:', error);
|
||||
addToast('Error al restablecer la categoría', { type: 'error' });
|
||||
},
|
||||
});
|
||||
};
|
||||
123
frontend/src/api/hooks/sustainability.ts
Normal file
123
frontend/src/api/hooks/sustainability.ts
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* React Query hooks for Sustainability API
|
||||
*/
|
||||
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
getSustainabilityMetrics,
|
||||
getSustainabilityWidgetData,
|
||||
getSDGCompliance,
|
||||
getEnvironmentalImpact,
|
||||
exportGrantReport
|
||||
} from '../services/sustainability';
|
||||
import type {
|
||||
SustainabilityMetrics,
|
||||
SustainabilityWidgetData,
|
||||
SDGCompliance,
|
||||
EnvironmentalImpact,
|
||||
GrantReport
|
||||
} from '../types/sustainability';
|
||||
|
||||
// Query keys
|
||||
export const sustainabilityKeys = {
|
||||
all: ['sustainability'] as const,
|
||||
metrics: (tenantId: string, startDate?: string, endDate?: string) =>
|
||||
['sustainability', 'metrics', tenantId, startDate, endDate] as const,
|
||||
widget: (tenantId: string, days: number) =>
|
||||
['sustainability', 'widget', tenantId, days] as const,
|
||||
sdg: (tenantId: string) =>
|
||||
['sustainability', 'sdg', tenantId] as const,
|
||||
environmental: (tenantId: string, days: number) =>
|
||||
['sustainability', 'environmental', tenantId, days] as const,
|
||||
};
|
||||
|
||||
/**
|
||||
* Hook to get comprehensive sustainability metrics
|
||||
*/
|
||||
export function useSustainabilityMetrics(
|
||||
tenantId: string,
|
||||
startDate?: string,
|
||||
endDate?: string,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: sustainabilityKeys.metrics(tenantId, startDate, endDate),
|
||||
queryFn: () => getSustainabilityMetrics(tenantId, startDate, endDate),
|
||||
enabled: options?.enabled !== false && !!tenantId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
refetchInterval: 10 * 60 * 1000, // Refetch every 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get sustainability widget data (simplified metrics)
|
||||
*/
|
||||
export function useSustainabilityWidget(
|
||||
tenantId: string,
|
||||
days: number = 30,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: sustainabilityKeys.widget(tenantId, days),
|
||||
queryFn: () => getSustainabilityWidgetData(tenantId, days),
|
||||
enabled: options?.enabled !== false && !!tenantId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
refetchInterval: 10 * 60 * 1000, // Refetch every 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get SDG 12.3 compliance status
|
||||
*/
|
||||
export function useSDGCompliance(
|
||||
tenantId: string,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: sustainabilityKeys.sdg(tenantId),
|
||||
queryFn: () => getSDGCompliance(tenantId),
|
||||
enabled: options?.enabled !== false && !!tenantId,
|
||||
staleTime: 10 * 60 * 1000, // 10 minutes
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get environmental impact data
|
||||
*/
|
||||
export function useEnvironmentalImpact(
|
||||
tenantId: string,
|
||||
days: number = 30,
|
||||
options?: { enabled?: boolean }
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: sustainabilityKeys.environmental(tenantId, days),
|
||||
queryFn: () => getEnvironmentalImpact(tenantId, days),
|
||||
enabled: options?.enabled !== false && !!tenantId,
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to export grant report
|
||||
*/
|
||||
export function useExportGrantReport() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: ({
|
||||
tenantId,
|
||||
grantType,
|
||||
startDate,
|
||||
endDate
|
||||
}: {
|
||||
tenantId: string;
|
||||
grantType?: string;
|
||||
startDate?: string;
|
||||
endDate?: string;
|
||||
}) => exportGrantReport(tenantId, grantType, startDate, endDate),
|
||||
onSuccess: () => {
|
||||
// Optionally invalidate related queries
|
||||
queryClient.invalidateQueries({ queryKey: sustainabilityKeys.all });
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -250,12 +250,38 @@ export class POSService {
|
||||
async getPOSTransaction(params: {
|
||||
tenant_id: string;
|
||||
transaction_id: string;
|
||||
}): Promise<{
|
||||
transaction: POSTransaction;
|
||||
}> {
|
||||
}): Promise<POSTransaction> {
|
||||
const { tenant_id, transaction_id } = params;
|
||||
const url = `/tenants/${tenant_id}${this.basePath}/transactions/${transaction_id}`;
|
||||
|
||||
|
||||
return apiClient.get(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get POS transactions dashboard summary
|
||||
*/
|
||||
async getPOSTransactionsDashboard(params: {
|
||||
tenant_id: string;
|
||||
}): Promise<{
|
||||
total_transactions_today: number;
|
||||
total_transactions_this_week: number;
|
||||
total_transactions_this_month: number;
|
||||
revenue_today: number;
|
||||
revenue_this_week: number;
|
||||
revenue_this_month: number;
|
||||
average_transaction_value: number;
|
||||
status_breakdown: Record<string, number>;
|
||||
payment_method_breakdown: Record<string, number>;
|
||||
sync_status: {
|
||||
synced: number;
|
||||
pending: number;
|
||||
failed: number;
|
||||
last_sync_at?: string;
|
||||
};
|
||||
}> {
|
||||
const { tenant_id } = params;
|
||||
const url = `/tenants/${tenant_id}${this.basePath}/operations/transactions-dashboard`;
|
||||
|
||||
return apiClient.get(url);
|
||||
}
|
||||
|
||||
|
||||
152
frontend/src/api/services/settings.ts
Normal file
152
frontend/src/api/services/settings.ts
Normal file
@@ -0,0 +1,152 @@
|
||||
// frontend/src/api/services/settings.ts
|
||||
/**
|
||||
* API service for Tenant Settings
|
||||
* Handles all HTTP requests for tenant operational configuration
|
||||
*/
|
||||
|
||||
import { apiClient } from '../client/apiClient';
|
||||
import type {
|
||||
TenantSettings,
|
||||
TenantSettingsUpdate,
|
||||
SettingsCategory,
|
||||
CategoryResetResponse,
|
||||
} from '../types/settings';
|
||||
|
||||
export const settingsApi = {
|
||||
/**
|
||||
* Get all settings for a tenant
|
||||
*/
|
||||
getSettings: async (tenantId: string): Promise<TenantSettings> => {
|
||||
try {
|
||||
console.log('🔍 Fetching settings for tenant:', tenantId);
|
||||
const response = await apiClient.get<TenantSettings>(`/tenants/${tenantId}/settings`);
|
||||
console.log('📊 Settings API response data:', response);
|
||||
|
||||
// Validate the response data structure
|
||||
if (!response) {
|
||||
throw new Error('Settings response data is null or undefined');
|
||||
}
|
||||
|
||||
if (!response.tenant_id) {
|
||||
throw new Error('Settings response missing tenant_id');
|
||||
}
|
||||
|
||||
if (!response.procurement_settings) {
|
||||
throw new Error('Settings response missing procurement_settings');
|
||||
}
|
||||
|
||||
console.log('✅ Settings data validation passed');
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ Error fetching settings:', error);
|
||||
console.error('Error details:', {
|
||||
message: (error as Error).message,
|
||||
stack: (error as Error).stack,
|
||||
tenantId
|
||||
});
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update tenant settings (partial update supported)
|
||||
*/
|
||||
updateSettings: async (
|
||||
tenantId: string,
|
||||
updates: TenantSettingsUpdate
|
||||
): Promise<TenantSettings> => {
|
||||
try {
|
||||
console.log('🔍 Updating settings for tenant:', tenantId, 'with updates:', updates);
|
||||
const response = await apiClient.put<TenantSettings>(`/tenants/${tenantId}/settings`, updates);
|
||||
console.log('📊 Settings update response:', response);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Settings update response data is null or undefined');
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ Error updating settings:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get settings for a specific category
|
||||
*/
|
||||
getCategorySettings: async (
|
||||
tenantId: string,
|
||||
category: SettingsCategory
|
||||
): Promise<Record<string, any>> => {
|
||||
try {
|
||||
console.log('🔍 Fetching category settings for tenant:', tenantId, 'category:', category);
|
||||
const response = await apiClient.get<{ tenant_id: string; category: string; settings: Record<string, any> }>(
|
||||
`/tenants/${tenantId}/settings/${category}`
|
||||
);
|
||||
console.log('📊 Category settings response:', response);
|
||||
|
||||
if (!response || !response.settings) {
|
||||
throw new Error('Category settings response data is null or undefined');
|
||||
}
|
||||
|
||||
return response.settings;
|
||||
} catch (error) {
|
||||
console.error('❌ Error fetching category settings:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Update settings for a specific category
|
||||
*/
|
||||
updateCategorySettings: async (
|
||||
tenantId: string,
|
||||
category: SettingsCategory,
|
||||
settings: Record<string, any>
|
||||
): Promise<TenantSettings> => {
|
||||
try {
|
||||
console.log('🔍 Updating category settings for tenant:', tenantId, 'category:', category, 'settings:', settings);
|
||||
const response = await apiClient.put<TenantSettings>(
|
||||
`/tenants/${tenantId}/settings/${category}`,
|
||||
{ settings }
|
||||
);
|
||||
console.log('📊 Category settings update response:', response);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Category settings update response data is null or undefined');
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ Error updating category settings:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Reset a category to default values
|
||||
*/
|
||||
resetCategory: async (
|
||||
tenantId: string,
|
||||
category: SettingsCategory
|
||||
): Promise<CategoryResetResponse> => {
|
||||
try {
|
||||
console.log('🔍 Resetting category for tenant:', tenantId, 'category:', category);
|
||||
const response = await apiClient.post<CategoryResetResponse>(
|
||||
`/tenants/${tenantId}/settings/${category}/reset`
|
||||
);
|
||||
console.log('📊 Category reset response:', response);
|
||||
|
||||
if (!response) {
|
||||
throw new Error('Category reset response data is null or undefined');
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
console.error('❌ Error resetting category:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default settingsApi;
|
||||
85
frontend/src/api/services/sustainability.ts
Normal file
85
frontend/src/api/services/sustainability.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Sustainability API Service
|
||||
* Environmental impact, SDG compliance, and grant reporting
|
||||
*/
|
||||
|
||||
import apiClient from '../client/apiClient';
|
||||
import type {
|
||||
SustainabilityMetrics,
|
||||
SustainabilityWidgetData,
|
||||
SDGCompliance,
|
||||
EnvironmentalImpact,
|
||||
GrantReport
|
||||
} from '../types/sustainability';
|
||||
|
||||
const BASE_PATH = '/sustainability';
|
||||
|
||||
/**
|
||||
* Get comprehensive sustainability metrics
|
||||
*/
|
||||
export async function getSustainabilityMetrics(
|
||||
tenantId: string,
|
||||
startDate?: string,
|
||||
endDate?: string
|
||||
): Promise<SustainabilityMetrics> {
|
||||
const params = new URLSearchParams();
|
||||
if (startDate) params.append('start_date', startDate);
|
||||
if (endDate) params.append('end_date', endDate);
|
||||
|
||||
const queryString = params.toString();
|
||||
const url = `/tenants/${tenantId}${BASE_PATH}/metrics${queryString ? `?${queryString}` : ''}`;
|
||||
|
||||
return await apiClient.get<SustainabilityMetrics>(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get simplified sustainability widget data
|
||||
*/
|
||||
export async function getSustainabilityWidgetData(
|
||||
tenantId: string,
|
||||
days: number = 30
|
||||
): Promise<SustainabilityWidgetData> {
|
||||
return await apiClient.get<SustainabilityWidgetData>(
|
||||
`/tenants/${tenantId}${BASE_PATH}/widget?days=${days}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SDG 12.3 compliance status
|
||||
*/
|
||||
export async function getSDGCompliance(tenantId: string): Promise<SDGCompliance> {
|
||||
return await apiClient.get<SDGCompliance>(
|
||||
`/tenants/${tenantId}${BASE_PATH}/sdg-compliance`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get environmental impact metrics
|
||||
*/
|
||||
export async function getEnvironmentalImpact(
|
||||
tenantId: string,
|
||||
days: number = 30
|
||||
): Promise<EnvironmentalImpact> {
|
||||
return await apiClient.get<EnvironmentalImpact>(
|
||||
`/tenants/${tenantId}${BASE_PATH}/environmental-impact?days=${days}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Export grant application report
|
||||
*/
|
||||
export async function exportGrantReport(
|
||||
tenantId: string,
|
||||
grantType: string = 'general',
|
||||
startDate?: string,
|
||||
endDate?: string
|
||||
): Promise<GrantReport> {
|
||||
const payload: any = { grant_type: grantType, format: 'json' };
|
||||
if (startDate) payload.start_date = startDate;
|
||||
if (endDate) payload.end_date = endDate;
|
||||
|
||||
return await apiClient.post<GrantReport>(
|
||||
`/tenants/${tenantId}${BASE_PATH}/export/grant-report`,
|
||||
payload
|
||||
);
|
||||
}
|
||||
117
frontend/src/api/types/settings.ts
Normal file
117
frontend/src/api/types/settings.ts
Normal file
@@ -0,0 +1,117 @@
|
||||
// frontend/src/api/types/settings.ts
|
||||
/**
|
||||
* TypeScript types for Tenant Settings
|
||||
* Operational configuration for bakery tenants
|
||||
*/
|
||||
|
||||
export interface ProcurementSettings {
|
||||
auto_approve_enabled: boolean;
|
||||
auto_approve_threshold_eur: number;
|
||||
auto_approve_min_supplier_score: number;
|
||||
require_approval_new_suppliers: boolean;
|
||||
require_approval_critical_items: boolean;
|
||||
procurement_lead_time_days: number;
|
||||
demand_forecast_days: number;
|
||||
safety_stock_percentage: number;
|
||||
po_approval_reminder_hours: number;
|
||||
po_critical_escalation_hours: number;
|
||||
}
|
||||
|
||||
export interface InventorySettings {
|
||||
low_stock_threshold: number;
|
||||
reorder_point: number;
|
||||
reorder_quantity: number;
|
||||
expiring_soon_days: number;
|
||||
expiration_warning_days: number;
|
||||
quality_score_threshold: number;
|
||||
temperature_monitoring_enabled: boolean;
|
||||
refrigeration_temp_min: number;
|
||||
refrigeration_temp_max: number;
|
||||
freezer_temp_min: number;
|
||||
freezer_temp_max: number;
|
||||
room_temp_min: number;
|
||||
room_temp_max: number;
|
||||
temp_deviation_alert_minutes: number;
|
||||
critical_temp_deviation_minutes: number;
|
||||
}
|
||||
|
||||
export interface ProductionSettings {
|
||||
planning_horizon_days: number;
|
||||
minimum_batch_size: number;
|
||||
maximum_batch_size: number;
|
||||
production_buffer_percentage: number;
|
||||
working_hours_per_day: number;
|
||||
max_overtime_hours: number;
|
||||
capacity_utilization_target: number;
|
||||
capacity_warning_threshold: number;
|
||||
quality_check_enabled: boolean;
|
||||
minimum_yield_percentage: number;
|
||||
quality_score_threshold: number;
|
||||
schedule_optimization_enabled: boolean;
|
||||
prep_time_buffer_minutes: number;
|
||||
cleanup_time_buffer_minutes: number;
|
||||
labor_cost_per_hour_eur: number;
|
||||
overhead_cost_percentage: number;
|
||||
}
|
||||
|
||||
export interface SupplierSettings {
|
||||
default_payment_terms_days: number;
|
||||
default_delivery_days: number;
|
||||
excellent_delivery_rate: number;
|
||||
good_delivery_rate: number;
|
||||
excellent_quality_rate: number;
|
||||
good_quality_rate: number;
|
||||
critical_delivery_delay_hours: number;
|
||||
critical_quality_rejection_rate: number;
|
||||
high_cost_variance_percentage: number;
|
||||
}
|
||||
|
||||
export interface POSSettings {
|
||||
sync_interval_minutes: number;
|
||||
auto_sync_products: boolean;
|
||||
auto_sync_transactions: boolean;
|
||||
}
|
||||
|
||||
export interface OrderSettings {
|
||||
max_discount_percentage: number;
|
||||
default_delivery_window_hours: number;
|
||||
dynamic_pricing_enabled: boolean;
|
||||
discount_enabled: boolean;
|
||||
delivery_tracking_enabled: boolean;
|
||||
}
|
||||
|
||||
export interface TenantSettings {
|
||||
id: string;
|
||||
tenant_id: string;
|
||||
procurement_settings: ProcurementSettings;
|
||||
inventory_settings: InventorySettings;
|
||||
production_settings: ProductionSettings;
|
||||
supplier_settings: SupplierSettings;
|
||||
pos_settings: POSSettings;
|
||||
order_settings: OrderSettings;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface TenantSettingsUpdate {
|
||||
procurement_settings?: Partial<ProcurementSettings>;
|
||||
inventory_settings?: Partial<InventorySettings>;
|
||||
production_settings?: Partial<ProductionSettings>;
|
||||
supplier_settings?: Partial<SupplierSettings>;
|
||||
pos_settings?: Partial<POSSettings>;
|
||||
order_settings?: Partial<OrderSettings>;
|
||||
}
|
||||
|
||||
export type SettingsCategory =
|
||||
| 'procurement'
|
||||
| 'inventory'
|
||||
| 'production'
|
||||
| 'supplier'
|
||||
| 'pos'
|
||||
| 'order';
|
||||
|
||||
export interface CategoryResetResponse {
|
||||
category: string;
|
||||
settings: Record<string, any>;
|
||||
message: string;
|
||||
}
|
||||
161
frontend/src/api/types/sustainability.ts
Normal file
161
frontend/src/api/types/sustainability.ts
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* Sustainability TypeScript Types
|
||||
* Environmental impact, SDG compliance, and grant reporting
|
||||
*/
|
||||
|
||||
export interface PeriodInfo {
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
days: number;
|
||||
}
|
||||
|
||||
export interface WasteMetrics {
|
||||
total_waste_kg: number;
|
||||
production_waste_kg: number;
|
||||
expired_waste_kg: number;
|
||||
waste_percentage: number;
|
||||
waste_by_reason: Record<string, number>;
|
||||
}
|
||||
|
||||
export interface CO2Emissions {
|
||||
kg: number;
|
||||
tons: number;
|
||||
trees_to_offset: number;
|
||||
}
|
||||
|
||||
export interface WaterFootprint {
|
||||
liters: number;
|
||||
cubic_meters: number;
|
||||
}
|
||||
|
||||
export interface LandUse {
|
||||
square_meters: number;
|
||||
hectares: number;
|
||||
}
|
||||
|
||||
export interface HumanEquivalents {
|
||||
car_km_equivalent: number;
|
||||
smartphone_charges: number;
|
||||
showers_equivalent: number;
|
||||
trees_planted: number;
|
||||
}
|
||||
|
||||
export interface EnvironmentalImpact {
|
||||
co2_emissions: CO2Emissions;
|
||||
water_footprint: WaterFootprint;
|
||||
land_use: LandUse;
|
||||
human_equivalents: HumanEquivalents;
|
||||
}
|
||||
|
||||
export interface SDG123Metrics {
|
||||
baseline_waste_percentage: number;
|
||||
current_waste_percentage: number;
|
||||
reduction_achieved: number;
|
||||
target_reduction: number;
|
||||
progress_to_target: number;
|
||||
status: 'sdg_compliant' | 'on_track' | 'progressing' | 'baseline';
|
||||
status_label: string;
|
||||
target_waste_percentage: number;
|
||||
}
|
||||
|
||||
export interface SDGCompliance {
|
||||
sdg_12_3: SDG123Metrics;
|
||||
baseline_period: string;
|
||||
certification_ready: boolean;
|
||||
improvement_areas: string[];
|
||||
}
|
||||
|
||||
export interface EnvironmentalImpactAvoided {
|
||||
co2_kg: number;
|
||||
water_liters: number;
|
||||
}
|
||||
|
||||
export interface AvoidedWaste {
|
||||
waste_avoided_kg: number;
|
||||
ai_assisted_batches: number;
|
||||
environmental_impact_avoided: EnvironmentalImpactAvoided;
|
||||
methodology: string;
|
||||
}
|
||||
|
||||
export interface FinancialImpact {
|
||||
waste_cost_eur: number;
|
||||
cost_per_kg: number;
|
||||
potential_monthly_savings: number;
|
||||
annual_projection: number;
|
||||
}
|
||||
|
||||
export interface GrantProgramEligibility {
|
||||
eligible: boolean;
|
||||
confidence: 'high' | 'medium' | 'low';
|
||||
requirements_met: boolean;
|
||||
}
|
||||
|
||||
export interface GrantReadiness {
|
||||
overall_readiness_percentage: number;
|
||||
grant_programs: Record<string, GrantProgramEligibility>;
|
||||
recommended_applications: string[];
|
||||
}
|
||||
|
||||
export interface SustainabilityMetrics {
|
||||
period: PeriodInfo;
|
||||
waste_metrics: WasteMetrics;
|
||||
environmental_impact: EnvironmentalImpact;
|
||||
sdg_compliance: SDGCompliance;
|
||||
avoided_waste: AvoidedWaste;
|
||||
financial_impact: FinancialImpact;
|
||||
grant_readiness: GrantReadiness;
|
||||
}
|
||||
|
||||
export interface SustainabilityWidgetData {
|
||||
total_waste_kg: number;
|
||||
waste_reduction_percentage: number;
|
||||
co2_saved_kg: number;
|
||||
water_saved_liters: number;
|
||||
trees_equivalent: number;
|
||||
sdg_status: string;
|
||||
sdg_progress: number;
|
||||
grant_programs_ready: number;
|
||||
financial_savings_eur: number;
|
||||
}
|
||||
|
||||
// Grant Report Types
|
||||
|
||||
export interface BaselineComparison {
|
||||
baseline: number;
|
||||
current: number;
|
||||
improvement: number;
|
||||
}
|
||||
|
||||
export interface SupportingData {
|
||||
baseline_comparison: BaselineComparison;
|
||||
environmental_benefits: EnvironmentalImpact;
|
||||
financial_benefits: FinancialImpact;
|
||||
}
|
||||
|
||||
export interface Certifications {
|
||||
sdg_12_3_compliant: boolean;
|
||||
grant_programs_eligible: string[];
|
||||
}
|
||||
|
||||
export interface ExecutiveSummary {
|
||||
total_waste_reduced_kg: number;
|
||||
waste_reduction_percentage: number;
|
||||
co2_emissions_avoided_kg: number;
|
||||
financial_savings_eur: number;
|
||||
sdg_compliance_status: string;
|
||||
}
|
||||
|
||||
export interface ReportMetadata {
|
||||
generated_at: string;
|
||||
report_type: string;
|
||||
period: PeriodInfo;
|
||||
tenant_id: string;
|
||||
}
|
||||
|
||||
export interface GrantReport {
|
||||
report_metadata: ReportMetadata;
|
||||
executive_summary: ExecutiveSummary;
|
||||
detailed_metrics: SustainabilityMetrics;
|
||||
certifications: Certifications;
|
||||
supporting_data: SupportingData;
|
||||
}
|
||||
Reference in New Issue
Block a user