Enhance club rankings retrieval and member TTR updates

Updated the getClubRankings method in myTischtennisClient to include an optional parameter for current rankings. Modified memberService to fetch both current and quarterly TTR values, improving member data accuracy. Enhanced the TeamManagementView to display (Q)TTR values for better user visibility. Added error handling for QTTR retrieval, ensuring robustness in member updates.
This commit is contained in:
Torsten Schulz (local)
2025-11-03 09:35:04 +01:00
parent e32871a005
commit f4411a4ee5
3 changed files with 72 additions and 22 deletions

View File

@@ -190,14 +190,14 @@ class MyTischtennisClient {
* @param {string} fedNickname - Federation nickname (e.g., "HeTTV")
* @returns {Promise<Object>} Rankings with player entries (all pages)
*/
async getClubRankings(cookie, clubId, fedNickname) {
async getClubRankings(cookie, clubId, fedNickname, currentRanking = 'yes') {
const allEntries = [];
let currentPage = 0;
let hasMorePages = true;
while (hasMorePages) {
const endpoint = `/rankings/andro-rangliste?all-players=on&clubnr=${clubId}&fednickname=${fedNickname}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`;
const endpoint = `/rankings/andro-rangliste?all-players=on&clubnr=${clubId}&fednickname=${fedNickname}&current-ranking=${currentRanking}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`;
const result = await this.authenticatedRequest(endpoint, cookie, {

View File

@@ -219,28 +219,42 @@ class MemberService {
};
}
// 2. Rangliste vom Verein abrufen
const rankings = await myTischtennisClient.getClubRankings(
// 2. Ranglisten vom Verein abrufen
// TTR (aktuell)
const rankingsCurrent = await myTischtennisClient.getClubRankings(
session.cookie,
account.clubId,
account.fedNickname
account.fedNickname,
'yes'
);
// QTTR (Quartalswert)
const rankingsQuarter = await myTischtennisClient.getClubRankings(
session.cookie,
account.clubId,
account.fedNickname,
'no'
);
if (!rankings.success) {
if (!rankingsCurrent.success) {
return {
status: 500,
response: {
message: rankings.error || 'Fehler beim Abrufen der Rangliste',
message: rankingsCurrent.error || 'Fehler beim Abrufen der Rangliste (aktuell)',
updated: 0,
errors: [],
debug: {
clubId: account.clubId,
fedNickname: account.fedNickname,
rankingsError: rankings.error
rankingsError: rankingsCurrent.error
}
}
};
}
if (!rankingsQuarter.success) {
// QTTR optional; nicht hart abbrechen, aber vermerken
console.warn('[updateRatingsFromMyTischtennis] - QTTR Abruf fehlgeschlagen:', rankingsQuarter.error);
}
// 3. Alle Mitglieder des Clubs laden
const members = await Member.findAll({ where: { clubId } });
@@ -250,29 +264,45 @@ class MemberService {
const notFound = [];
const matched = [];
// 4. Für jedes Mitglied TTR aktualisieren
// Maps für schnelleres Matching
const mapByName = (entries) => {
const m = new Map();
for (const e of (entries || [])) {
const key = `${(e.firstname||'').toLowerCase()}|${(e.lastname||'').toLowerCase()}`;
if (!m.has(key)) m.set(key, e);
}
return m;
};
const currentMap = mapByName(rankingsCurrent.entries);
const quarterMap = rankingsQuarter.success ? mapByName(rankingsQuarter.entries) : new Map();
// 4. Für jedes Mitglied TTR und QTTR aktualisieren
for (const member of members) {
const firstName = member.firstName;
const lastName = member.lastName;
// Suche nach Match in rankings entries
const rankingEntry = rankings.entries.find(entry =>
entry.firstname.toLowerCase() === firstName.toLowerCase() &&
entry.lastname.toLowerCase() === lastName.toLowerCase()
);
if (rankingEntry) {
const key = `${(firstName||'').toLowerCase()}|${(lastName||'').toLowerCase()}`;
const rankingEntry = currentMap.get(key);
const rankingQuarterEntry = quarterMap.get(key);
if (rankingEntry || rankingQuarterEntry) {
try {
// fedRank ist der TTR-Wert
const oldTtr = member.ttr;
member.ttr = rankingEntry.fedRank;
// TODO: QTTR muss von einem anderen Endpoint geholt werden
const oldQttr = member.qttr;
if (rankingEntry && typeof rankingEntry.fedRank === 'number') {
member.ttr = rankingEntry.fedRank;
}
if (rankingQuarterEntry && typeof rankingQuarterEntry.fedRank === 'number') {
member.qttr = rankingQuarterEntry.fedRank;
}
await member.save();
updated++;
matched.push({
name: `${firstName} ${lastName}`,
oldTtr: oldTtr,
newTtr: rankingEntry.fedRank
newTtr: member.ttr,
oldQttr: oldQttr,
newQttr: member.qttr
});
} catch (error) {
console.error(`[updateRatingsFromMyTischtennis] - Error updating ${firstName} ${lastName}:`, error);
@@ -304,7 +334,7 @@ class MemberService {
matched: matched,
notFound: notFound,
errors: errors,
totalEntries: rankings.entries.length,
totalEntries: rankingsCurrent.entries.length,
totalMembers: members.length
}
};

View File

@@ -67,6 +67,7 @@
<thead>
<tr>
<th>Spieler</th>
<th title="(Q)TTR-Wert">(Q)TTR</th>
<th title="Gesamte Saison (ab 1. Juli)">Saison</th>
<th :title="isSecondHalf ? 'Rückrunde (ab 1. Januar)' : 'Vorrunde (Juli - Dezember)'">
{{ isSecondHalf ? 'Rückrunde' : 'Vorrunde' }}
@@ -76,6 +77,12 @@
<tbody>
<tr v-for="stat in playerStats" :key="stat.memberId">
<td class="player-name">{{ stat.firstName }} {{ stat.lastName }}</td>
<td class="stat-value">
<span v-if="memberById[stat.memberId]">
{{ memberById[stat.memberId].qttr ?? memberById[stat.memberId].ttr ?? '' }}
</span>
<span v-else></span>
</td>
<td class="stat-value">{{ stat.totalSeason }}</td>
<td class="stat-value">{{ isSecondHalf ? stat.totalSecondHalf : stat.totalFirstHalf }}</td>
</tr>
@@ -392,6 +399,7 @@ export default {
// Player Stats
const playerStats = ref([]);
const loadingStats = ref(false);
const memberById = ref({});
// Computed
const selectedClub = computed(() => store.state.currentClub);
@@ -1012,6 +1020,18 @@ export default {
loadingStats.value = true;
try {
// Mitglieder mit (Q)TTR laden, um Werte anzuzeigen
try {
const membersResp = await apiClient.get(`/clubmembers/get/${selectedClub.value}/true`);
const map = {};
for (const m of membersResp.data || []) {
map[m.id] = { ttr: m.ttr ?? null, qttr: m.qttr ?? null };
}
memberById.value = map;
} catch (e) {
memberById.value = {};
}
const response = await apiClient.get(
`/matches/leagues/${selectedClub.value}/stats/${teamToEdit.value.leagueId}`,
{