class KreditorService { constructor() { // API is mounted under /api (see src/index.js). Keep consistent with AuthService. this.baseURL = '/api'; } async getAuthHeaders() { const token = localStorage.getItem('token'); return { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, }; } async handleResponse(response) { if (!response.ok) { const errorData = await response.json().catch(() => ({})); console.log('Server error response:', errorData); // Handle different types of errors with clearer messages if (response.status === 502 || response.status === 503) { throw new Error('FibDash Service nicht verfügbar - Bitte versuchen Sie es später erneut'); } else if (response.status === 500) { throw new Error('FibDash Server Fehler - Bitte kontaktieren Sie den Administrator'); } else if (response.status === 403) { const message = errorData.message || 'Zugriff verweigert'; throw new Error(message); } else if (response.status === 401) { throw new Error('Authentifizierung fehlgeschlagen - Bitte melden Sie sich erneut an'); } else if (response.status === 404) { throw new Error('Kreditor nicht gefunden'); } else if (response.status === 409) { const message = errorData.error || 'Kreditor bereits vorhanden'; throw new Error(message); } else if (response.status === 400) { const message = errorData.error || 'Ungültige Daten'; throw new Error(message); } else { const errorMessage = errorData.error || errorData.message || `HTTP ${response.status}: Unbekannter Fehler`; throw new Error(errorMessage); } } return await response.json(); } async getAllKreditors() { try { const url = `${this.baseURL}/data/kreditors`; const response = await fetch(url, { method: 'GET', headers: await this.getAuthHeaders(), }); return await this.handleResponse(response); } catch (error) { console.error('Error fetching kreditors:', error); if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut'); } throw error; } } // Convenience: find kreditor by kreditorId (string compare) async findKreditorByCode(kreditorId) { const all = await this.getAllKreditors(); return (all || []).find(k => String(k.kreditorId).trim() === String(kreditorId).trim()); } async getKreditorById(id) { try { const url = `${this.baseURL}/data/kreditors/${id}`; const response = await fetch(url, { method: 'GET', headers: await this.getAuthHeaders(), }); return await this.handleResponse(response); } catch (error) { console.error('Error fetching kreditor:', error); if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut'); } throw error; } } async createKreditor(kreditorData) { try { const url = `${this.baseURL}/data/kreditors`; console.debug('[KreditorService] POST', url, kreditorData); const response = await fetch(url, { method: 'POST', headers: await this.getAuthHeaders(), body: JSON.stringify(kreditorData), }); return await this.handleResponse(response); } catch (error) { // Map unique constraint errors to a clearer duplicate message when possible const msg = (error && error.message) || ''; if (/unique|bereits vorhanden|already exists|kreditor/i.test(msg)) { throw new Error('Kreditor bereits vorhanden'); } console.error('Error creating kreditor:', error); if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut'); } throw error; } } async updateKreditor(id, kreditorData) { try { const url = `${this.baseURL}/data/kreditors/${id}`; const response = await fetch(url, { method: 'PUT', headers: await this.getAuthHeaders(), body: JSON.stringify(kreditorData), }); return await this.handleResponse(response); } catch (error) { console.error('Error updating kreditor:', error); if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut'); } throw error; } } async deleteKreditor(id) { try { const url = `${this.baseURL}/data/kreditors/${id}`; const response = await fetch(url, { method: 'DELETE', headers: await this.getAuthHeaders(), }); return await this.handleResponse(response); } catch (error) { console.error('Error deleting kreditor:', error); if (error instanceof TypeError && error.message.includes('fetch')) { throw new Error('FibDash Service nicht erreichbar - Prüfen Sie Ihre Internetverbindung oder versuchen Sie es später erneut'); } throw error; } } // Utility method to validate kreditor data validateKreditorData(kreditorData) { const errors = []; // IBAN is only required for non-banking accounts that are not manual assignments const isBanking = kreditorData.is_banking || false; const hasIban = kreditorData.iban && kreditorData.iban.trim() !== ''; if (!isBanking && !hasIban) { errors.push('IBAN ist erforderlich (außer für Banking-Konten oder manuelle Zuordnungen)'); } if (!kreditorData.name || kreditorData.name.trim() === '') { errors.push('Name ist erforderlich'); } if (!kreditorData.kreditorId || kreditorData.kreditorId.trim() === '') { errors.push('Kreditor-ID ist erforderlich'); } // Basic IBAN format validation (simplified) - only if IBAN is provided if (hasIban && !/^[A-Z]{2}[0-9]{2}[A-Z0-9]{4}[0-9]{7}([A-Z0-9]?){0,16}$/i.test(kreditorData.iban.replace(/\s/g, ''))) { errors.push('IBAN Format ist ungültig'); } // Validate kreditorId format (should start with 70xxx for regular kreditors) if (kreditorData.kreditorId && !isBanking && !/^70\d{3,}$/.test(kreditorData.kreditorId)) { errors.push('Kreditor-ID muss mit 70 beginnen gefolgt von mindestens 3 Ziffern (außer für Banking-Konten)'); } // For banking accounts, warn about special handling if (isBanking && hasIban) { // This is just informational, not an error console.info('Banking-Konto erkannt: Transaktionen benötigen manuelle Kreditor-Zuordnung'); } return errors; } } export default KreditorService;