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:
@@ -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}¤t-ranking=${currentRanking}&results-per-page=100&page=${currentPage}&_data=routes%2F%24`;
|
||||
|
||||
|
||||
const result = await this.authenticatedRequest(endpoint, cookie, {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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}`,
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user