2025-08-03 17:48:34 +02:00
|
|
|
// frontend/src/api/services/data.service.ts
|
|
|
|
|
/**
|
|
|
|
|
* Data Management Service
|
|
|
|
|
* Handles sales data operations
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
import { apiClient } from '../client';
|
|
|
|
|
import { RequestTimeouts } from '../client/config';
|
|
|
|
|
import type {
|
|
|
|
|
SalesData,
|
2025-08-04 09:00:18 +02:00
|
|
|
SalesValidationResult,
|
2025-08-03 17:48:34 +02:00
|
|
|
SalesDataQuery,
|
|
|
|
|
SalesDataImport,
|
|
|
|
|
SalesImportResult,
|
|
|
|
|
DashboardStats,
|
|
|
|
|
PaginatedResponse,
|
|
|
|
|
ActivityItem,
|
|
|
|
|
} from '../types';
|
|
|
|
|
|
|
|
|
|
export class DataService {
|
|
|
|
|
/**
|
|
|
|
|
* Upload Sales History File
|
|
|
|
|
*/
|
|
|
|
|
async uploadSalesHistory(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
file: File,
|
|
|
|
|
additionalData?: Record<string, any>
|
|
|
|
|
): Promise<SalesImportResult> {
|
|
|
|
|
// Determine file format
|
|
|
|
|
const fileName = file.name.toLowerCase();
|
|
|
|
|
let fileFormat: string;
|
|
|
|
|
|
|
|
|
|
if (fileName.endsWith('.csv')) {
|
|
|
|
|
fileFormat = 'csv';
|
|
|
|
|
} else if (fileName.endsWith('.json')) {
|
|
|
|
|
fileFormat = 'json';
|
|
|
|
|
} else if (fileName.endsWith('.xlsx') || fileName.endsWith('.xls')) {
|
|
|
|
|
fileFormat = 'excel';
|
|
|
|
|
} else {
|
|
|
|
|
fileFormat = 'csv'; // Default fallback
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const uploadData = {
|
|
|
|
|
file_format: fileFormat,
|
|
|
|
|
...additionalData,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return apiClient.upload(
|
|
|
|
|
`/tenants/${tenantId}/sales/import`,
|
|
|
|
|
file,
|
|
|
|
|
uploadData,
|
|
|
|
|
{
|
|
|
|
|
timeout: RequestTimeouts.LONG,
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Validate Sales Data
|
|
|
|
|
*/
|
|
|
|
|
async validateSalesData(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
file: File
|
2025-08-04 09:00:18 +02:00
|
|
|
): Promise<SalesValidationResult> {
|
2025-08-03 17:48:34 +02:00
|
|
|
const fileName = file.name.toLowerCase();
|
|
|
|
|
let fileFormat: string;
|
|
|
|
|
|
|
|
|
|
if (fileName.endsWith('.csv')) {
|
|
|
|
|
fileFormat = 'csv';
|
|
|
|
|
} else if (fileName.endsWith('.json')) {
|
|
|
|
|
fileFormat = 'json';
|
|
|
|
|
} else if (fileName.endsWith('.xlsx') || fileName.endsWith('.xls')) {
|
|
|
|
|
fileFormat = 'excel';
|
|
|
|
|
} else {
|
|
|
|
|
fileFormat = 'csv';
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return apiClient.upload(
|
2025-08-04 09:00:18 +02:00
|
|
|
`/tenants/${tenantId}/sales/import/validate`,
|
2025-08-03 17:48:34 +02:00
|
|
|
file,
|
|
|
|
|
{
|
|
|
|
|
file_format: fileFormat,
|
|
|
|
|
validate_only: true,
|
2025-08-04 09:00:18 +02:00
|
|
|
source: 'onboarding_upload',
|
2025-08-03 17:48:34 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
timeout: RequestTimeouts.MEDIUM,
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Sales Data
|
|
|
|
|
*/
|
|
|
|
|
async getSalesData(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
query?: SalesDataQuery
|
|
|
|
|
): Promise<PaginatedResponse<SalesData>> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/sales`, { params: query });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Single Sales Record
|
|
|
|
|
*/
|
|
|
|
|
async getSalesRecord(tenantId: string, recordId: string): Promise<SalesData> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/sales/${recordId}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Update Sales Record
|
|
|
|
|
*/
|
|
|
|
|
async updateSalesRecord(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
recordId: string,
|
|
|
|
|
data: Partial<SalesData>
|
|
|
|
|
): Promise<SalesData> {
|
|
|
|
|
return apiClient.put(`/tenants/${tenantId}/sales/${recordId}`, data);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Delete Sales Record
|
|
|
|
|
*/
|
|
|
|
|
async deleteSalesRecord(tenantId: string, recordId: string): Promise<{ message: string }> {
|
|
|
|
|
return apiClient.delete(`/tenants/${tenantId}/sales/${recordId}`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Dashboard Statistics
|
|
|
|
|
*/
|
|
|
|
|
async getDashboardStats(tenantId: string): Promise<DashboardStats> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/sales/stats`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Analytics Data
|
|
|
|
|
*/
|
|
|
|
|
async getAnalytics(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
params?: {
|
|
|
|
|
start_date?: string;
|
|
|
|
|
end_date?: string;
|
|
|
|
|
product_names?: string[];
|
|
|
|
|
metrics?: string[];
|
|
|
|
|
}
|
|
|
|
|
): Promise<any> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/analytics`, { params });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Export Sales Data
|
|
|
|
|
*/
|
|
|
|
|
async exportSalesData(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
format: 'csv' | 'excel' | 'json',
|
|
|
|
|
query?: SalesDataQuery
|
|
|
|
|
): Promise<Blob> {
|
|
|
|
|
const response = await apiClient.request(`/tenants/${tenantId}/sales/export`, {
|
|
|
|
|
method: 'GET',
|
|
|
|
|
params: { ...query, format },
|
|
|
|
|
headers: {
|
|
|
|
|
'Accept': format === 'csv' ? 'text/csv' :
|
|
|
|
|
format === 'excel' ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' :
|
|
|
|
|
'application/json',
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
return new Blob([response], {
|
|
|
|
|
type: format === 'csv' ? 'text/csv' :
|
|
|
|
|
format === 'excel' ? 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' :
|
|
|
|
|
'application/json',
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Recent Activity
|
|
|
|
|
*/
|
|
|
|
|
async getRecentActivity(tenantId: string, limit?: number): Promise<ActivityItem[]> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/activity`, {
|
|
|
|
|
params: { limit },
|
|
|
|
|
});
|
|
|
|
|
}
|
2025-08-04 21:46:12 +02:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Products List from Sales Data
|
|
|
|
|
* This should be added to the DataService class
|
|
|
|
|
*/
|
|
|
|
|
async getProductsList(tenantId: string): Promise<string[]> {
|
|
|
|
|
const response = await apiClient.get(`/tenants/${tenantId}/sales/products`);
|
|
|
|
|
|
|
|
|
|
// Extract product names from the response
|
|
|
|
|
return response.map((product: any) =>
|
|
|
|
|
product.name || product.product_name || product
|
|
|
|
|
).filter(Boolean);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Current Weather Data
|
|
|
|
|
* This should be added to the DataService class
|
|
|
|
|
*/
|
|
|
|
|
async getCurrentWeather(lat: number, lon: number): Promise<{
|
|
|
|
|
temperature: number;
|
|
|
|
|
description: string;
|
|
|
|
|
precipitation: number;
|
|
|
|
|
humidity?: number;
|
|
|
|
|
wind_speed?: number;
|
|
|
|
|
}> {
|
|
|
|
|
return apiClient.get(`/data/weather/current`, {
|
|
|
|
|
params: { lat, lon }
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Weather Forecast
|
|
|
|
|
* This should be added to the DataService class
|
|
|
|
|
*/
|
|
|
|
|
async getWeatherForecast(
|
|
|
|
|
lat: number,
|
|
|
|
|
lon: number,
|
|
|
|
|
days: number = 7
|
|
|
|
|
): Promise<any[]> {
|
|
|
|
|
return apiClient.get(`/data/weather/forecast`, {
|
|
|
|
|
params: { lat, lon, days }
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Sales Summary by Period
|
|
|
|
|
* This should be added to the DataService class
|
|
|
|
|
*/
|
|
|
|
|
async getSalesSummary(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
period: 'daily' | 'weekly' | 'monthly' = 'daily'
|
|
|
|
|
): Promise<any> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/sales/summary`, {
|
|
|
|
|
params: { period }
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get Sales Analytics
|
|
|
|
|
* This should be added to the DataService class
|
|
|
|
|
*/
|
|
|
|
|
async getSalesAnalytics(
|
|
|
|
|
tenantId: string,
|
|
|
|
|
startDate?: string,
|
|
|
|
|
endDate?: string
|
|
|
|
|
): Promise<{
|
|
|
|
|
total_revenue: number;
|
|
|
|
|
waste_reduction_percentage?: number;
|
|
|
|
|
forecast_accuracy?: number;
|
|
|
|
|
stockout_events?: number;
|
|
|
|
|
}> {
|
|
|
|
|
return apiClient.get(`/tenants/${tenantId}/sales/analytics`, {
|
|
|
|
|
params: {
|
|
|
|
|
start_date: startDate,
|
|
|
|
|
end_date: endDate
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2025-08-03 17:48:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const dataService = new DataService();
|