import axios from 'axios'; import type { ApiResponse, Customer, Contract, ContractTask, ContractTaskSubtask, ContractTaskStatus, SalesPlatform, CancellationPeriod, ContractDuration, ContractCategory, Provider, Tariff, User, Address, BankCard, IdentityDocument, Meter, MeterReading, Invoice, Role, PortalSettings, CustomerRepresentative, CustomerSummary } from '../types'; const api = axios.create({ baseURL: '/api', headers: { 'Content-Type': 'application/json', }, }); // Add auth token to requests api.interceptors.request.use((config) => { const token = localStorage.getItem('token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // Handle auth errors and extract error messages api.interceptors.response.use( (response) => response, (error) => { // Bei 401 nur dann zur Login-Seite umleiten, wenn wir NICHT gerade auf der Login-Seite sind // Login-Endpunkte ausschließen, da 401 dort "falsches Passwort" bedeutet const isLoginEndpoint = error.config?.url?.includes('/auth/login') || error.config?.url?.includes('/auth/customer-login'); if (error.response?.status === 401 && !isLoginEndpoint) { localStorage.removeItem('token'); localStorage.removeItem('user'); window.location.href = '/login'; } // Extract error message from response const message = error.response?.data?.error || error.message || 'Ein Fehler ist aufgetreten'; const enhancedError = new Error(message); return Promise.reject(enhancedError); } ); // Auth export const authApi = { login: async (email: string, password: string) => { const res = await api.post>('/auth/login', { email, password }); return res.data; }, customerLogin: async (email: string, password: string) => { const res = await api.post>('/auth/customer-login', { email, password }); return res.data; }, me: async () => { const res = await api.get>('/auth/me'); return res.data; }, }; // Customers export const customerApi = { getAll: async (params?: { search?: string; type?: string; page?: number; limit?: number }) => { const res = await api.get>('/customers', { params }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/customers/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/customers', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/customers/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/customers/${id}`); return res.data; }, // Portal-Einstellungen getPortalSettings: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/portal`); return res.data; }, updatePortalSettings: async (customerId: number, data: { portalEnabled?: boolean; portalEmail?: string | null }) => { const res = await api.put>(`/customers/${customerId}/portal`, data); return res.data; }, setPortalPassword: async (customerId: number, password: string) => { const res = await api.post>(`/customers/${customerId}/portal/password`, { password }); return res.data; }, getPortalPassword: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/portal/password`); return res.data; }, // Vertreter-Verwaltung getRepresentatives: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/representatives`); return res.data; }, addRepresentative: async (customerId: number, representativeId: number, notes?: string) => { const res = await api.post>(`/customers/${customerId}/representatives`, { representativeId, notes }); return res.data; }, removeRepresentative: async (customerId: number, representativeId: number) => { const res = await api.delete>(`/customers/${customerId}/representatives/${representativeId}`); return res.data; }, searchForRepresentative: async (customerId: number, search: string) => { const res = await api.get>(`/customers/${customerId}/representatives/search`, { params: { search } }); return res.data; }, }; // Addresses export const addressApi = { getByCustomer: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/addresses`); return res.data; }, create: async (customerId: number, data: Partial
) => { const res = await api.post>(`/customers/${customerId}/addresses`, data); return res.data; }, update: async (id: number, data: Partial
) => { const res = await api.put>(`/addresses/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/addresses/${id}`); return res.data; }, }; // Bank Cards export const bankCardApi = { getByCustomer: async (customerId: number, showInactive = false) => { const res = await api.get>(`/customers/${customerId}/bank-cards`, { params: { showInactive } }); return res.data; }, create: async (customerId: number, data: Partial) => { const res = await api.post>(`/customers/${customerId}/bank-cards`, data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/bank-cards/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/bank-cards/${id}`); return res.data; }, }; // Identity Documents export const documentApi = { getByCustomer: async (customerId: number, showInactive = false) => { const res = await api.get>(`/customers/${customerId}/documents`, { params: { showInactive } }); return res.data; }, create: async (customerId: number, data: Partial) => { const res = await api.post>(`/customers/${customerId}/documents`, data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/documents/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/documents/${id}`); return res.data; }, }; // Meters export const meterApi = { getByCustomer: async (customerId: number, showInactive = false) => { const res = await api.get>(`/customers/${customerId}/meters`, { params: { showInactive } }); return res.data; }, create: async (customerId: number, data: Partial) => { const res = await api.post>(`/customers/${customerId}/meters`, data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/meters/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/meters/${id}`); return res.data; }, getReadings: async (meterId: number) => { const res = await api.get>(`/meters/${meterId}/readings`); return res.data; }, addReading: async (meterId: number, data: Partial) => { const res = await api.post>(`/meters/${meterId}/readings`, data); return res.data; }, updateReading: async (meterId: number, readingId: number, data: Partial) => { const res = await api.put>(`/meters/${meterId}/readings/${readingId}`, data); return res.data; }, deleteReading: async (meterId: number, readingId: number) => { const res = await api.delete>(`/meters/${meterId}/readings/${readingId}`); return res.data; }, }; // Invoice API export const invoiceApi = { getInvoices: async (ecdId: number) => { const res = await api.get>(`/energy-details/${ecdId}/invoices`); return res.data; }, addInvoice: async (ecdId: number, data: Partial) => { const res = await api.post>(`/energy-details/${ecdId}/invoices`, data); return res.data; }, updateInvoice: async (ecdId: number, invoiceId: number, data: Partial) => { const res = await api.put>(`/energy-details/${ecdId}/invoices/${invoiceId}`, data); return res.data; }, deleteInvoice: async (ecdId: number, invoiceId: number) => { const res = await api.delete>(`/energy-details/${ecdId}/invoices/${invoiceId}`); return res.data; }, uploadDocument: async (invoiceId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>( `/upload/invoices/${invoiceId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } } ); return res.data; }, deleteDocument: async (invoiceId: number) => { const res = await api.delete>(`/upload/invoices/${invoiceId}`); return res.data; }, }; // Stressfrei-Wechseln E-Mail-Adressen export interface StressfreiEmail { id: number; customerId: number; email: string; platform?: string; notes?: string; isActive: boolean; hasMailbox: boolean; createdAt: string; updatedAt: string; } // Mailbox-Konto (für Dropdown-Auswahl) export interface MailboxAccount { id: number; email: string; notes?: string; hasMailbox: boolean; _count: { cachedEmails: number; }; } // Gecachte E-Mail export interface CachedEmail { id: number; stressfreiEmailId: number; folder: 'INBOX' | 'SENT'; messageId: string; uid: number; subject?: string; fromAddress: string; fromName?: string; toAddresses: string; // JSON Array ccAddresses?: string; // JSON Array receivedAt: string; textBody?: string; htmlBody?: string; hasAttachments: boolean; attachmentNames?: string; // JSON Array contractId?: number; assignedAt?: string; assignedBy?: number; isAutoAssigned?: boolean; // true = automatisch beim Senden aus Vertrag zugeordnet isRead: boolean; isStarred: boolean; isDeleted: boolean; deletedAt?: string; createdAt: string; updatedAt: string; stressfreiEmail?: { id: number; email: string; customerId: number; }; contract?: { id: number; contractNumber: string; } | null; } export interface SyncResult { newEmails: number; totalEmails: number; } export interface EmailAttachment { filename: string; content: string; // Base64-kodierter Inhalt contentType?: string; // MIME-Type (z.B. 'application/pdf') } export interface SendEmailParams { to: string | string[]; cc?: string | string[]; subject: string; text?: string; html?: string; inReplyTo?: string; references?: string[]; attachments?: EmailAttachment[]; contractId?: number; // Vertrag dem die gesendete E-Mail zugeordnet wird } // Anhang-Speicher-Ziele export interface AttachmentTargetSlot { key: string; label: string; field: string; hasDocument: boolean; currentPath?: string; } export interface AttachmentEntityWithSlots { id: number; label: string; slots: AttachmentTargetSlot[]; } export interface AttachmentTargetsResponse { customer: { id: number; name: string; type: 'PRIVATE' | 'BUSINESS'; slots: AttachmentTargetSlot[]; }; identityDocuments: AttachmentEntityWithSlots[]; bankCards: AttachmentEntityWithSlots[]; contract?: { id: number; contractNumber: string; type: string; energyDetailsId?: number; slots: AttachmentTargetSlot[]; }; } export const stressfreiEmailApi = { getByCustomer: async (customerId: number, includeInactive = false) => { const res = await api.get>(`/customers/${customerId}/stressfrei-emails`, { params: { includeInactive } }); return res.data; }, create: async (customerId: number, data: { email: string; platform?: string; notes?: string; provisionAtProvider?: boolean; createMailbox?: boolean; }) => { const res = await api.post>(`/customers/${customerId}/stressfrei-emails`, data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/stressfrei-emails/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/stressfrei-emails/${id}`); return res.data; }, // Mailbox nachträglich aktivieren enableMailbox: async (id: number) => { const res = await api.post>(`/stressfrei-emails/${id}/enable-mailbox`); return res.data; }, // Mailbox-Status mit Provider synchronisieren syncMailboxStatus: async (id: number) => { const res = await api.post>(`/stressfrei-emails/${id}/sync-mailbox-status`); return res.data; }, // Mailbox-Zugangsdaten abrufen (IMAP/SMTP) getMailboxCredentials: async (id: number) => { const res = await api.get>(`/stressfrei-emails/${id}/credentials`); return res.data; }, // Passwort zurücksetzen (generiert neues Passwort beim Provider) resetPassword: async (id: number) => { const res = await api.post>(`/stressfrei-emails/${id}/reset-password`); return res.data; }, // E-Mails synchronisieren syncEmails: async (id: number, fullSync = false) => { const res = await api.post>(`/stressfrei-emails/${id}/sync`, {}, { params: { full: fullSync } }); return res.data; }, // E-Mail senden sendEmail: async (id: number, params: SendEmailParams) => { const res = await api.post>(`/stressfrei-emails/${id}/send`, params); return res.data; }, // Ordner-Anzahlen abrufen (total und ungelesen pro Ordner) getFolderCounts: async (id: number) => { const res = await api.get>(`/stressfrei-emails/${id}/folder-counts`); return res.data; }, }; // Cached Email API (E-Mail-Client) export const cachedEmailApi = { // E-Mails für Kunden abrufen getForCustomer: async (customerId: number, options?: { accountId?: number; folder?: 'INBOX' | 'SENT'; limit?: number; offset?: number }) => { const res = await api.get>(`/customers/${customerId}/emails`, { params: options }); return res.data; }, // E-Mails für Vertrag abrufen getForContract: async (contractId: number, options?: { folder?: 'INBOX' | 'SENT'; limit?: number; offset?: number }) => { const res = await api.get>(`/contracts/${contractId}/emails`, { params: options }); return res.data; }, // Ordner-Anzahlen für Vertrag abrufen (zugeordnete E-Mails) getContractFolderCounts: async (contractId: number) => { const res = await api.get>(`/contracts/${contractId}/emails/folder-counts`); return res.data; }, // Mailbox-Konten eines Kunden abrufen getMailboxAccounts: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/mailbox-accounts`); return res.data; }, // Einzelne E-Mail abrufen (mit Body) getById: async (id: number) => { const res = await api.get>(`/emails/${id}`); return res.data; }, // E-Mail-Thread abrufen getThread: async (id: number) => { const res = await api.get>(`/emails/${id}/thread`); return res.data; }, // Als gelesen/ungelesen markieren markAsRead: async (id: number, isRead: boolean) => { const res = await api.patch>(`/emails/${id}/read`, { isRead }); return res.data; }, // Stern umschalten toggleStar: async (id: number) => { const res = await api.post>(`/emails/${id}/star`); return res.data; }, // Vertrag zuordnen assignToContract: async (emailId: number, contractId: number) => { const res = await api.post>(`/emails/${emailId}/assign`, { contractId }); return res.data; }, // Zuordnung aufheben unassignFromContract: async (emailId: number) => { const res = await api.delete>(`/emails/${emailId}/assign`); return res.data; }, // E-Mail löschen (nur Admin) delete: async (emailId: number) => { const res = await api.delete>(`/emails/${emailId}`); return res.data; }, // Anhang-URL (view=true für inline anzeigen, sonst download) getAttachmentUrl: (emailId: number, filename: string, view?: boolean) => { const token = localStorage.getItem('token'); const encodedFilename = encodeURIComponent(filename); const viewParam = view ? '&view=true' : ''; return `${api.defaults.baseURL}/emails/${emailId}/attachments/${encodedFilename}?token=${token}${viewParam}`; }, // Ungelesene E-Mails zählen getUnreadCount: async (params: { customerId?: number; contractId?: number }) => { const res = await api.get>('/emails/unread-count', { params }); return res.data; }, // ==================== PAPIERKORB ==================== // Papierkorb-E-Mails für Kunden abrufen getTrash: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/emails/trash`); return res.data; }, // Papierkorb-Anzahl für Kunden getTrashCount: async (customerId: number) => { const res = await api.get>(`/customers/${customerId}/emails/trash/count`); return res.data; }, // E-Mail aus Papierkorb wiederherstellen restore: async (emailId: number) => { const res = await api.post>(`/emails/${emailId}/restore`); return res.data; }, // E-Mail endgültig löschen (aus Papierkorb) permanentDelete: async (emailId: number) => { const res = await api.delete>(`/emails/${emailId}/permanent`); return res.data; }, // ==================== ANHANG-SPEICHERUNG ==================== // Verfügbare Dokumenten-Ziele für Anhänge abrufen getAttachmentTargets: async (emailId: number) => { const res = await api.get>(`/emails/${emailId}/attachment-targets`); return res.data; }, // Anhang in Dokumentenfeld speichern saveAttachmentTo: async (emailId: number, filename: string, params: { entityType: string; entityId?: number; targetKey: string }) => { const encodedFilename = encodeURIComponent(filename); const res = await api.post>( `/emails/${emailId}/attachments/${encodedFilename}/save-to`, params ); return res.data; }, // E-Mail als PDF speichern saveEmailAsPdf: async (emailId: number, params: { entityType: string; entityId?: number; targetKey: string }) => { const res = await api.post>( `/emails/${emailId}/save-as-pdf`, params ); return res.data; }, // E-Mail als Rechnung speichern (für Energieverträge) saveEmailAsInvoice: async (emailId: number, params: { invoiceDate: string; invoiceType: string; notes?: string }) => { const res = await api.post>( `/emails/${emailId}/save-as-invoice`, params ); return res.data; }, // Anhang als Rechnung speichern (für Energieverträge) saveAttachmentAsInvoice: async (emailId: number, filename: string, params: { invoiceDate: string; invoiceType: string; notes?: string }) => { const encodedFilename = encodeURIComponent(filename); const res = await api.post>( `/emails/${emailId}/attachments/${encodedFilename}/save-as-invoice`, params ); return res.data; }, }; // Contracts - Vertragsbaum für Kundenansicht export interface ContractTreeNodeContract { id: number; contractNumber: string; type: string; status: string; startDate: string | null; endDate: string | null; providerName: string | null; tariffName: string | null; previousContractId: number | null; provider?: { id: number; name: string } | null; tariff?: { id: number; name: string } | null; contractCategory?: { id: number; name: string } | null; } export interface ContractTreeNode { contract: ContractTreeNodeContract; predecessors: ContractTreeNode[]; hasHistory: boolean; } export const contractApi = { getAll: async (params?: { customerId?: number; type?: string; status?: string; search?: string; page?: number; limit?: number }) => { const res = await api.get>('/contracts', { params }); return res.data; }, getTreeForCustomer: async (customerId: number) => { const res = await api.get>('/contracts', { params: { customerId, tree: 'true' } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/contracts/${id}`); return res.data; }, create: async (data: Partial & { [key: string]: unknown }) => { const res = await api.post>('/contracts', data); return res.data; }, update: async (id: number, data: Partial & { [key: string]: unknown }) => { const res = await api.put>(`/contracts/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/contracts/${id}`); return res.data; }, createFollowUp: async (id: number) => { const res = await api.post>(`/contracts/${id}/follow-up`); return res.data; }, getPassword: async (id: number) => { const res = await api.get>(`/contracts/${id}/password`); return res.data; }, getSimCardCredentials: async (simCardId: number) => { const res = await api.get>(`/contracts/simcard/${simCardId}/credentials`); return res.data; }, getInternetCredentials: async (contractId: number) => { const res = await api.get>(`/contracts/${contractId}/internet-credentials`); return res.data; }, getSipCredentials: async (phoneNumberId: number) => { const res = await api.get>(`/contracts/phonenumber/${phoneNumberId}/sip-credentials`); return res.data; }, // Vertrags-Cockpit getCockpit: async () => { const res = await api.get>('/contracts/cockpit'); return res.data; }, }; // Contract Tasks (Aufgaben) export const contractTaskApi = { // Alle Tasks über alle Verträge (für Task-Liste & Dashboard) getAll: async (params?: { status?: ContractTaskStatus; customerId?: number }) => { const res = await api.get>('/tasks', { params }); return res.data; }, // Task-Statistik (offene Aufgaben) getStats: async () => { const res = await api.get>('/tasks/stats'); return res.data; }, // Tasks für einen spezifischen Vertrag getByContract: async (contractId: number, status?: ContractTaskStatus) => { const res = await api.get>(`/contracts/${contractId}/tasks`, { params: { status } }); return res.data; }, create: async (contractId: number, data: { title: string; description?: string; visibleInPortal?: boolean }) => { const res = await api.post>(`/contracts/${contractId}/tasks`, data); return res.data; }, update: async (taskId: number, data: { title?: string; description?: string; visibleInPortal?: boolean }) => { const res = await api.put>(`/tasks/${taskId}`, data); return res.data; }, complete: async (taskId: number) => { const res = await api.post>(`/tasks/${taskId}/complete`); return res.data; }, reopen: async (taskId: number) => { const res = await api.post>(`/tasks/${taskId}/reopen`); return res.data; }, delete: async (taskId: number) => { const res = await api.delete>(`/tasks/${taskId}`); return res.data; }, // Subtasks createSubtask: async (taskId: number, title: string) => { const res = await api.post>(`/tasks/${taskId}/subtasks`, { title }); return res.data; }, // Kundenportal: Antwort auf eigenes Ticket createReply: async (taskId: number, title: string) => { const res = await api.post>(`/tasks/${taskId}/reply`, { title }); return res.data; }, updateSubtask: async (subtaskId: number, title: string) => { const res = await api.put>(`/subtasks/${subtaskId}`, { title }); return res.data; }, completeSubtask: async (subtaskId: number) => { const res = await api.post>(`/subtasks/${subtaskId}/complete`); return res.data; }, reopenSubtask: async (subtaskId: number) => { const res = await api.post>(`/subtasks/${subtaskId}/reopen`); return res.data; }, deleteSubtask: async (subtaskId: number) => { const res = await api.delete>(`/subtasks/${subtaskId}`); return res.data; }, // Support-Ticket erstellen (für Kundenportal) createSupportTicket: async (contractId: number, data: { title: string; description?: string }) => { const res = await api.post>(`/contracts/${contractId}/support-ticket`, data); return res.data; }, }; // App Settings export const appSettingsApi = { getPublic: async () => { const res = await api.get>>('/settings/public'); return res.data; }, getAll: async () => { const res = await api.get>>('/settings'); return res.data; }, update: async (settings: Record) => { const res = await api.put>('/settings', settings); return res.data; }, updateOne: async (key: string, value: string) => { const res = await api.put>(`/settings/${key}`, { value }); return res.data; }, }; // Backup & Restore export interface BackupInfo { name: string; timestamp: string; totalRecords: number; tables: { table: string; count: number }[]; sizeBytes: number; hasUploads: boolean; uploadSizeBytes: number; } export const backupApi = { list: async () => { const res = await api.get>('/settings/backups'); return res.data; }, create: async () => { const res = await api.post>('/settings/backup'); return res.data; }, restore: async (name: string) => { const res = await api.post>(`/settings/backup/${name}/restore`); return res.data; }, delete: async (name: string) => { const res = await api.delete>(`/settings/backup/${name}`); return res.data; }, getDownloadUrl: (name: string) => { return `/api/settings/backup/${name}/download`; }, upload: async (file: File) => { const formData = new FormData(); formData.append('backup', file); const res = await api.post>('/settings/backup/upload', formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, factoryReset: async () => { const res = await api.post>('/settings/factory-reset'); return res.data; }, }; // Platforms export const platformApi = { getAll: async (includeInactive = false) => { const res = await api.get>('/platforms', { params: { includeInactive } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/platforms/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/platforms', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/platforms/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/platforms/${id}`); return res.data; }, }; // Cancellation Periods export const cancellationPeriodApi = { getAll: async (includeInactive = false) => { const res = await api.get>('/cancellation-periods', { params: { includeInactive } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/cancellation-periods/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/cancellation-periods', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/cancellation-periods/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/cancellation-periods/${id}`); return res.data; }, }; // Contract Durations export const contractDurationApi = { getAll: async (includeInactive = false) => { const res = await api.get>('/contract-durations', { params: { includeInactive } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/contract-durations/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/contract-durations', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/contract-durations/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/contract-durations/${id}`); return res.data; }, }; // Contract Categories (Vertragstypen) export const contractCategoryApi = { getAll: async (includeInactive = false) => { const res = await api.get>('/contract-categories', { params: { includeInactive } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/contract-categories/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/contract-categories', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/contract-categories/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/contract-categories/${id}`); return res.data; }, }; // Providers (Anbieter) export const providerApi = { getAll: async (includeInactive = false) => { const res = await api.get>('/providers', { params: { includeInactive } }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/providers/${id}`); return res.data; }, create: async (data: Partial) => { const res = await api.post>('/providers', data); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/providers/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/providers/${id}`); return res.data; }, getTariffs: async (providerId: number, includeInactive = false) => { const res = await api.get>(`/providers/${providerId}/tariffs`, { params: { includeInactive } }); return res.data; }, createTariff: async (providerId: number, data: Partial) => { const res = await api.post>(`/providers/${providerId}/tariffs`, data); return res.data; }, }; // Tariffs (Tarife) export const tariffApi = { getById: async (id: number) => { const res = await api.get>(`/tariffs/${id}`); return res.data; }, update: async (id: number, data: Partial) => { const res = await api.put>(`/tariffs/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/tariffs/${id}`); return res.data; }, }; // Upload export const uploadApi = { uploadBankCardDocument: async (bankCardId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/bank-cards/${bankCardId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, uploadIdentityDocument: async (documentId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/documents/${documentId}`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteBankCardDocument: async (bankCardId: number) => { const res = await api.delete>(`/upload/bank-cards/${bankCardId}`); return res.data; }, deleteIdentityDocument: async (documentId: number) => { const res = await api.delete>(`/upload/documents/${documentId}`); return res.data; }, uploadBusinessRegistration: async (customerId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/customers/${customerId}/business-registration`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteBusinessRegistration: async (customerId: number) => { const res = await api.delete>(`/upload/customers/${customerId}/business-registration`); return res.data; }, uploadCommercialRegister: async (customerId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/customers/${customerId}/commercial-register`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteCommercialRegister: async (customerId: number) => { const res = await api.delete>(`/upload/customers/${customerId}/commercial-register`); return res.data; }, uploadPrivacyPolicy: async (customerId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/customers/${customerId}/privacy-policy`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deletePrivacyPolicy: async (customerId: number) => { const res = await api.delete>(`/upload/customers/${customerId}/privacy-policy`); return res.data; }, // Contract Documents uploadCancellationLetter: async (contractId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/contracts/${contractId}/cancellation-letter`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteCancellationLetter: async (contractId: number) => { const res = await api.delete>(`/upload/contracts/${contractId}/cancellation-letter`); return res.data; }, uploadCancellationConfirmation: async (contractId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/contracts/${contractId}/cancellation-confirmation`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteCancellationConfirmation: async (contractId: number) => { const res = await api.delete>(`/upload/contracts/${contractId}/cancellation-confirmation`); return res.data; }, uploadCancellationLetterOptions: async (contractId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/contracts/${contractId}/cancellation-letter-options`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteCancellationLetterOptions: async (contractId: number) => { const res = await api.delete>(`/upload/contracts/${contractId}/cancellation-letter-options`); return res.data; }, uploadCancellationConfirmationOptions: async (contractId: number, file: File) => { const formData = new FormData(); formData.append('document', file); const res = await api.post>(`/upload/contracts/${contractId}/cancellation-confirmation-options`, formData, { headers: { 'Content-Type': 'multipart/form-data' }, }); return res.data; }, deleteCancellationConfirmationOptions: async (contractId: number) => { const res = await api.delete>(`/upload/contracts/${contractId}/cancellation-confirmation-options`); return res.data; }, }; // Users export const userApi = { getAll: async (params?: { search?: string; isActive?: boolean; roleId?: number; page?: number; limit?: number }) => { const res = await api.get>('/users', { params }); return res.data; }, getById: async (id: number) => { const res = await api.get>(`/users/${id}`); return res.data; }, create: async (data: { email: string; password: string; firstName: string; lastName: string; roleIds: number[]; customerId?: number; hasDeveloperAccess?: boolean }) => { const res = await api.post>('/users', data); return res.data; }, update: async (id: number, data: Partial & { password?: string; roleIds?: number[] }) => { const res = await api.put>(`/users/${id}`, data); return res.data; }, delete: async (id: number) => { const res = await api.delete>(`/users/${id}`); return res.data; }, getRoles: async () => { const res = await api.get>('/users/roles/list'); return res.data; }, }; // Developer export const developerApi = { getSchema: async () => { const res = await api.get>('/developer/schema'); return res.data; }, getTableData: async (tableName: string, page = 1, limit = 50) => { const res = await api.get>(`/developer/table/${tableName}`, { params: { page, limit } }); return res.data; }, updateRow: async (tableName: string, id: string, data: Record) => { const res = await api.put>(`/developer/table/${tableName}/${id}`, data); return res.data; }, deleteRow: async (tableName: string, id: string) => { const res = await api.delete>(`/developer/table/${tableName}/${id}`); return res.data; }, getReference: async (tableName: string) => { const res = await api.get>(`/developer/reference/${tableName}`); return res.data; }, }; // Email Provider (für Stressfrei-Wechseln Provisionierung) export interface EmailProviderConfig { id: number; name: string; type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN'; apiUrl: string; apiKey?: string; username?: string; passwordEncrypted?: string; domain: string; defaultForwardEmail?: string; // IMAP/SMTP-Server (für E-Mail-Client) imapServer?: string; imapPort?: number; smtpServer?: string; smtpPort?: number; // Verschlüsselungs-Einstellungen imapEncryption?: 'SSL' | 'STARTTLS' | 'NONE'; smtpEncryption?: 'SSL' | 'STARTTLS' | 'NONE'; allowSelfSignedCerts?: boolean; // Selbstsignierte Zertifikate erlauben isActive: boolean; isDefault: boolean; createdAt: string; updatedAt: string; } export interface EmailOperationResult { success: boolean; message?: string; error?: string; } export const emailProviderApi = { // Config CRUD getConfigs: async () => { const res = await api.get>('/email-providers/configs'); return res.data; }, getConfig: async (id: number) => { const res = await api.get>(`/email-providers/configs/${id}`); return res.data; }, createConfig: async (data: Partial & { password?: string }) => { const res = await api.post>('/email-providers/configs', data); return res.data; }, updateConfig: async (id: number, data: Partial & { password?: string }) => { const res = await api.put>(`/email-providers/configs/${id}`, data); return res.data; }, deleteConfig: async (id: number) => { const res = await api.delete>(`/email-providers/configs/${id}`); return res.data; }, // Email Operations testConnection: async (options?: { id?: number; testData?: { type: 'PLESK' | 'CPANEL' | 'DIRECTADMIN'; apiUrl: string; apiKey?: string; username?: string; password?: string; domain: string; }; }) => { const body = options?.testData ? { ...options.testData } : options?.id ? { id: options.id } : {}; const res = await api.post>('/email-providers/test-connection', body); return res.data; }, getDomain: async () => { const res = await api.get>('/email-providers/domain'); return res.data; }, checkEmailExists: async (localPart: string) => { const res = await api.get>(`/email-providers/check/${localPart}`); return res.data; }, provisionEmail: async (localPart: string, customerEmail: string) => { const res = await api.post>('/email-providers/provision', { localPart, customerEmail }); return res.data; }, deprovisionEmail: async (localPart: string) => { const res = await api.delete>(`/email-providers/deprovision/${localPart}`); return res.data; }, }; export default api;