diff --git a/backend/services/memberTransferService.js b/backend/services/memberTransferService.js index c83fb3b..7dd3e44 100644 --- a/backend/services/memberTransferService.js +++ b/backend/services/memberTransferService.js @@ -46,7 +46,73 @@ class MemberTransferService { }; } - // 2. Login durchführen + // 2. Mitglieder validieren und filtern + const validMembers = []; + const invalidMembers = []; + + for (const member of members) { + const validationErrors = []; + + // Pflichtfelder prüfen + if (!member.firstName || member.firstName.trim() === '') { + validationErrors.push('Vorname ist erforderlich'); + } + + if (!member.lastName || member.lastName.trim() === '') { + validationErrors.push('Nachname ist erforderlich'); + } + + // Geburtsdatum prüfen (wird als geburtsdatum im Template verwendet) + const birthDate = this.formatBirthDate(member.birthDate); + if (!birthDate || birthDate.trim() === '') { + validationErrors.push('Geburtsdatum ist erforderlich'); + } + + if (validationErrors.length > 0) { + invalidMembers.push({ + member: { + id: member.id, + firstName: member.firstName || '', + lastName: member.lastName || '' + }, + errors: validationErrors + }); + } else { + validMembers.push(member); + } + } + + // Wenn keine gültigen Mitglieder vorhanden sind + if (validMembers.length === 0) { + const errorMessages = invalidMembers.map(inv => { + const name = `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`; + return `${name}: ${inv.errors.join(', ')}`; + }).join('\n'); + + return { + status: 400, + response: { + success: false, + message: 'Keine gültigen Mitglieder zum Übertragen gefunden', + error: `Alle ${members.length} Mitglieder haben fehlende Pflichtfelder:\n${errorMessages}`, + transferred: 0, + total: members.length, + invalidMembers: invalidMembers, + errors: [] + } + }; + } + + // Logge gefilterte Mitglieder + if (invalidMembers.length > 0) { + infoLog(`[transferMembers] ${invalidMembers.length} Mitglieder wurden aufgrund fehlender Pflichtfelder ausgeschlossen`); + invalidMembers.forEach(inv => { + const name = `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`; + infoLog(`[transferMembers] Ausgeschlossen: ${name} - ${inv.errors.join(', ')}`); + }); + } + + // 3. Login durchführen let authToken = null; let sessionCookie = null; @@ -245,7 +311,7 @@ class MemberTransferService { const membersArray = []; const memberErrors = []; - for (const member of members) { + for (const member of validMembers) { try { const memberData = this.replacePlaceholders( config.transferTemplate, @@ -352,7 +418,7 @@ class MemberTransferService { const bulkErrors = transferResult.data?.results?.errors || []; const bulkDuplicates = transferResult.data?.results?.duplicates || []; - let message = `${transferred} von ${members.length} Mitglieder(n) erfolgreich übertragen.`; + let message = `${transferred} von ${validMembers.length} gültigen Mitglieder(n) erfolgreich übertragen.`; if (bulkDuplicates.length > 0) { message += ` ${bulkDuplicates.length} Duplikat(e) gefunden.`; } @@ -360,15 +426,34 @@ class MemberTransferService { message += ` ${bulkErrors.length + memberErrors.length} Fehler.`; } + // Kombiniere Fehler aus ungültigen Mitgliedern und Übertragungsfehlern + const allErrors = [ + ...invalidMembers.map(inv => ({ + member: `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`, + error: inv.errors.join(', ') + })), + ...bulkErrors, + ...memberErrors + ]; + + // Erweitere Nachricht um Informationen über ausgeschlossene Mitglieder + let finalMessage = message; + if (invalidMembers.length > 0) { + finalMessage += ` ${invalidMembers.length} Mitglieder wurden aufgrund fehlender Pflichtfelder ausgeschlossen.`; + } + return { status: 200, response: { success: true, - message: message, + message: finalMessage, transferred: transferred, total: members.length, + validCount: validMembers.length, + invalidCount: invalidMembers.length, duplicates: bulkDuplicates.length, - errors: [...bulkErrors, ...memberErrors], + invalidMembers: invalidMembers, + errors: allErrors, details: transferResult.data } }; @@ -392,6 +477,15 @@ class MemberTransferService { } } + // Kombiniere Fehler aus ungültigen Mitgliedern und Übertragungsfehlern + const allErrors = [ + ...invalidMembers.map(inv => ({ + member: `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`, + error: inv.errors.join(', ') + })), + ...memberErrors + ]; + return { status: transferResult.status || 500, response: { @@ -400,7 +494,8 @@ class MemberTransferService { error: errorMessage, transferred: 0, total: members.length, - errors: memberErrors + invalidMembers: invalidMembers, + errors: allErrors } }; } @@ -423,7 +518,15 @@ class MemberTransferService { const errors = []; let successCount = 0; - for (const member of members) { + // Füge Fehler für ungültige Mitglieder hinzu + for (const inv of invalidMembers) { + errors.push({ + member: `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`, + error: inv.errors.join(', ') + }); + } + + for (const member of validMembers) { try { const memberData = this.replacePlaceholders( config.transferTemplate, @@ -460,7 +563,10 @@ class MemberTransferService { } } - const message = `${successCount} von ${members.length} Mitglieder(n) erfolgreich übertragen.`; + let message = `${successCount} von ${validMembers.length} gültigen Mitglieder(n) erfolgreich übertragen.`; + if (invalidMembers.length > 0) { + message += ` ${invalidMembers.length} Mitglieder wurden aufgrund fehlender Pflichtfelder ausgeschlossen.`; + } return { status: 200, @@ -469,7 +575,10 @@ class MemberTransferService { message: message, transferred: successCount, total: members.length, + validCount: validMembers.length, + invalidCount: invalidMembers.length, results: results, + invalidMembers: invalidMembers, errors: errors } }; diff --git a/frontend/src/components/MemberTransferDialog.vue b/frontend/src/components/MemberTransferDialog.vue index 20b1e60..8442481 100644 --- a/frontend/src/components/MemberTransferDialog.vue +++ b/frontend/src/components/MemberTransferDialog.vue @@ -369,24 +369,50 @@ export default { `${response.data.transferred} von ${response.data.total} Mitglieder(n) erfolgreich übertragen.`; let details = ''; + + // Zeige ausgeschlossene Mitglieder an + if (response.data.invalidMembers && response.data.invalidMembers.length > 0) { + details += 'Ausgeschlossene Mitglieder (fehlende Pflichtfelder):\n'; + details += response.data.invalidMembers.map(inv => { + const name = `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`; + return `${name}: ${inv.errors.join(', ')}`; + }).join('\n'); + details += '\n\n'; + } + + // Zeige weitere Fehler an if (response.data.errors && response.data.errors.length > 0) { - details = 'Fehler:\n' + response.data.errors.map(e => + details += 'Weitere Fehler:\n'; + details += response.data.errors.map(e => `${e.member}: ${e.error}` ).join('\n'); } this.$emit('success', { message: message, - details: details, + details: details.trim(), results: response.data }); this.handleClose(); } else { + // Bei Fehlern auch ausgeschlossene Mitglieder anzeigen + let errorDetails = response.data.error || ''; + + if (response.data.invalidMembers && response.data.invalidMembers.length > 0) { + errorDetails += '\n\nAusgeschlossene Mitglieder (fehlende Pflichtfelder):\n'; + errorDetails += response.data.invalidMembers.map(inv => { + const name = `${inv.member.firstName} ${inv.member.lastName}`.trim() || `ID: ${inv.member.id}`; + return `${name}: ${inv.errors.join(', ')}`; + }).join('\n'); + } + this.$emit('error', { message: response.data.message || 'Übertragung fehlgeschlagen', - error: response.data.error + error: errorDetails }); + + this.handleClose(); } } catch (error) { console.error('Transfer error:', error); @@ -399,6 +425,8 @@ export default { message: 'Fehler bei der Übertragung', error: errorMessage }); + + this.handleClose(); } finally { this.isTransferring = false; }