Files
Novault-Frontend-web/src/services/reportService.ts

186 lines
4.5 KiB
TypeScript

/**
* Report Service
* Handles API calls for statistical reports and analysis
*/
import api from './api';
import type { CurrencyCode } from '../types';
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:2612/api/v1';
// Report API Response Types
export interface CurrencySummary {
currency: CurrencyCode;
total_income: number;
total_expense: number;
balance: number;
count: number;
}
export interface UnifiedSummary {
target_currency: CurrencyCode;
total_income: number;
total_expense: number;
balance: number;
conversion_date: string;
}
export interface TransactionSummaryResponse {
by_currency: CurrencySummary[];
unified?: UnifiedSummary;
}
export interface CategorySummaryItem {
category_id: number;
category_name: string;
currency?: CurrencyCode;
total_amount: number;
count: number;
percentage: number;
}
export interface CategorySummaryResponse {
by_currency: CategorySummaryItem[];
unified?: CategorySummaryItem[];
}
export interface TrendDataPoint {
Date: string;
TotalIncome: number;
TotalExpense: number;
Balance: number;
Count: number;
}
export interface TrendDataResponse {
period: 'day' | 'week' | 'month' | 'year';
currency?: CurrencyCode;
data_points: TrendDataPoint[];
}
export interface SummaryParams {
start_date: string;
end_date: string;
target_currency?: CurrencyCode;
conversion_date?: string;
}
export interface CategoryParams {
start_date: string;
end_date: string;
type: 'income' | 'expense';
target_currency?: CurrencyCode;
conversion_date?: string;
}
export interface TrendParams {
start_date: string;
end_date: string;
period: 'day' | 'week' | 'month' | 'year';
currency?: CurrencyCode;
}
export interface ExportParams {
start_date: string;
end_date: string;
format: 'pdf' | 'excel';
target_currency?: CurrencyCode;
}
/**
* Get transaction summary for a date range
*/
export const getTransactionSummary = async (
params: SummaryParams
): Promise<TransactionSummaryResponse> => {
const response = await api.get<{ success: boolean; data: TransactionSummaryResponse }>(
'/reports/summary',
params as unknown as Record<string, string | number | boolean | undefined>
);
if (!response.data) {
throw new Error('Failed to get transaction summary');
}
return response.data;
};
/**
* Get category summary for a date range
*/
export const getCategorySummary = async (
params: CategoryParams
): Promise<CategorySummaryResponse> => {
const response = await api.get<{ success: boolean; data: CategorySummaryResponse }>(
'/reports/category',
params as unknown as Record<string, string | number | boolean | undefined>
);
if (!response.data) {
throw new Error('Failed to get category summary');
}
return response.data;
};
/**
* Get trend data for a date range
*/
export const getTrendData = async (
params: TrendParams
): Promise<TrendDataResponse> => {
const response = await api.get<{ success: boolean; data: TrendDataResponse }>(
'/reports/trend',
params as unknown as Record<string, string | number | boolean | undefined>
);
if (!response.data) {
throw new Error('Failed to get trend data');
}
return response.data;
};
/**
* Export report as PDF or Excel
* Downloads the file directly to the user's device
*/
export const exportReport = async (params: ExportParams): Promise<void> => {
// Use fetch directly for blob response
const response = await fetch(`${API_BASE_URL}/reports/export`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || `Export failed with status: ${response.status}`);
}
// Get the blob from response
const blob = await response.blob();
// Create a temporary URL for the blob
const url = window.URL.createObjectURL(blob);
// Create a temporary anchor element and trigger download
const link = document.createElement('a');
link.href = url;
// Generate filename based on date range and format
const filename = `report_${params.start_date.replace(/-/g, '')}_to_${params.end_date.replace(/-/g, '')}.${params.format === 'pdf' ? 'pdf' : 'xlsx'}`;
link.download = filename;
// Trigger the download
document.body.appendChild(link);
link.click();
// Clean up
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
};
export default {
getTransactionSummary,
getCategorySummary,
getTrendData,
exportReport,
};