ec81940178
- 0.7: UI-Design-Richtlinien (docs/ui-design-guidelines.md, 535 lines) - 0.8: Theme-Customization Backend (4 theme fields, migration 0023) - 0.9: Theme-Customization Frontend (SettingsTheme.tsx, themeStore.ts, live preview) - 0.10: RBAC-Audit (4 plugins secured, 53 routes with require_permission) - 0.11: LiteLLM-Cleanup (llm_client.py migrated from httpx to litellm) - 0.12: KI-Agent-Framework docs (plugin-development-guide.md, agent_capabilities field) - 0.13: Heartbeat configurable (ProactiveSettings, migration 0024, frontend UI) - 0.14: Unified Search Field-Level RBAC (resolve_permissions + filter_fields_by_permission) - 0.15: Undo/History-System (EntityHistory model, service, routes, migration 0025, HistoryViewer) - 0.16: Storage Backend (LocalStorage + S3Storage, DMS/attachments/mail updated) - 0.17: Import/Export unified Contact fields (firstname, surname, email_1, phone_1) - 0.18: .gitignore & Config-Cleanup (webui→frontend, python-jose removed, .env untracked) - 0.19: Mail-Salt Security-Fix (per-account random salt, migration 0026) - 0.20: AGPL replaced (PyMuPDF→pypdf, OnlyOffice→Collabora, LICENSE + THIRD_PARTY_LICENSES.md)
201 lines
5.0 KiB
TypeScript
201 lines
5.0 KiB
TypeScript
/**
|
|
* System settings, currency, tax, and sequence hooks.
|
|
*/
|
|
|
|
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
|
import { apiGet, apiPost, apiPatch, apiDelete, apiClient } from './client';
|
|
|
|
export interface Currency {
|
|
id: string;
|
|
code: string;
|
|
name: string;
|
|
symbol: string;
|
|
is_default: boolean;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface TaxRate {
|
|
id: string;
|
|
name: string;
|
|
rate: number;
|
|
is_default: boolean;
|
|
country?: string | null;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface Sequence {
|
|
id: string;
|
|
name: string;
|
|
prefix: string;
|
|
next_number: number;
|
|
padding: number;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
export interface SystemSettings {
|
|
id?: string;
|
|
company_name: string;
|
|
company_legal_form?: string | null;
|
|
company_street: string;
|
|
company_city: string;
|
|
company_zip: string;
|
|
company_country: string;
|
|
tax_number?: string | null;
|
|
vat_id?: string | null;
|
|
iban?: string | null;
|
|
bic?: string | null;
|
|
bank_name?: string | null;
|
|
ceo?: string | null;
|
|
trade_register?: string | null;
|
|
default_currency_id?: string | null;
|
|
default_tax_id?: string | null;
|
|
invoice_prefix: string;
|
|
quote_prefix: string;
|
|
payment_terms_days: number;
|
|
// Theme customization
|
|
theme_primary_color?: string;
|
|
theme_accent_color?: string;
|
|
theme_font_family?: string;
|
|
theme_border_radius?: string;
|
|
created_at?: string;
|
|
updated_at?: string;
|
|
}
|
|
|
|
// System Settings
|
|
export function useSystemSettings() {
|
|
return useQuery({
|
|
queryKey: ['systemSettings'],
|
|
queryFn: () => apiGet<SystemSettings>('/system-settings'),
|
|
});
|
|
}
|
|
|
|
export function useUpdateSystemSettings() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (data: Partial<SystemSettings>) => apiClient.put('/system-settings', data).then(r => r.data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['systemSettings'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Currencies
|
|
export function useCurrencies() {
|
|
return useQuery({
|
|
queryKey: ['currencies'],
|
|
queryFn: () => apiGet<{ items: Currency[]; total: number }>('/currencies'),
|
|
});
|
|
}
|
|
|
|
export function useCreateCurrency() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (data: Partial<Currency>) => apiPost('/currencies', data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['currencies'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateCurrency() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: Partial<Currency> }) =>
|
|
apiPatch(`/currencies/${id}`, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['currencies'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteCurrency() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (id: string) => apiDelete(`/currencies/${id}`),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['currencies'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Taxes
|
|
export function useTaxes() {
|
|
return useQuery({
|
|
queryKey: ['taxes'],
|
|
queryFn: () => apiGet<{ items: TaxRate[]; total: number }>('/taxes'),
|
|
});
|
|
}
|
|
|
|
export function useCreateTax() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (data: Partial<TaxRate>) => apiPost('/taxes', data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['taxes'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateTax() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: Partial<TaxRate> }) =>
|
|
apiPatch(`/taxes/${id}`, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['taxes'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteTax() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (id: string) => apiDelete(`/taxes/${id}`),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['taxes'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
// Sequences
|
|
export function useSequences() {
|
|
return useQuery({
|
|
queryKey: ['sequences'],
|
|
queryFn: () => apiGet<{ items: Sequence[]; total: number }>('/sequences'),
|
|
});
|
|
}
|
|
|
|
export function useCreateSequence() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (data: Partial<Sequence>) => apiPost('/sequences', data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['sequences'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useUpdateSequence() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: ({ id, data }: { id: string; data: Partial<Sequence> }) =>
|
|
apiPatch(`/sequences/${id}`, data),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['sequences'] });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useDeleteSequence() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (id: string) => apiDelete(`/sequences/${id}`),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: ['sequences'] });
|
|
},
|
|
});
|
|
}
|