에버리지, 회원추가 로직 수정
This commit is contained in:
@@ -1020,8 +1020,27 @@ exports.updateEventScore = async (req, res) => {
|
||||
totalScore: score + handicap
|
||||
});
|
||||
|
||||
// 캐시 무효화 추가
|
||||
await averageService.invalidateMemberAverageCache(scoreRecord.participantId);
|
||||
// 캐시 무효화: participantId -> memberId로 변환 후 무효화 및 워밍업
|
||||
try {
|
||||
const ep = await EventParticipant.findOne({
|
||||
where: { id: scoreRecord.participantId },
|
||||
attributes: ['memberId'],
|
||||
});
|
||||
if (ep && ep.memberId) {
|
||||
await averageService.invalidateMemberAverageCache(ep.memberId);
|
||||
// clubId 조회 후 워밍업
|
||||
try {
|
||||
const ev = await Event.findOne({ where: { id: eventId }, attributes: ['clubId'] });
|
||||
if (ev && ev.clubId) {
|
||||
await averageService.calculateMemberAverageByClubSetting(ep.memberId, ev.clubId);
|
||||
}
|
||||
} catch (e2) {
|
||||
console.error('에버리지 워밍업 실패(updateEventScore):', e2);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('에버리지 캐시 무효화 실패(updateEventScore):', e);
|
||||
}
|
||||
|
||||
// 업데이트된 레코드 조회
|
||||
const updatedScore = await EventScore.findOne({
|
||||
@@ -1093,14 +1112,23 @@ exports.deleteEventScore = async (req, res) => {
|
||||
|
||||
await score.destroy();
|
||||
|
||||
// 점수 삭제 시 해당 회원의 에버리지 캡시 무효화
|
||||
if (score.participant && score.participant.Member) {
|
||||
try {
|
||||
await averageService.invalidateMemberAverageCache(score.participant.Member.id);
|
||||
console.log(`회원 ${score.participant.Member.id}의 에버리지 캡시 무효화 완료`);
|
||||
} catch (error) {
|
||||
console.error(`회원 ${score.participant.Member.id}의 에버리지 캡시 무효화 오류:`, error);
|
||||
// 점수 삭제 시 해당 회원의 에버리지 캐시 무효화 및 워밍업
|
||||
try {
|
||||
const memberId = score.EventParticipant?.Member?.id;
|
||||
if (memberId) {
|
||||
await averageService.invalidateMemberAverageCache(memberId);
|
||||
console.log(`회원 ${memberId}의 에버리지 캐시 무효화 완료`);
|
||||
// clubId는 상단 검증 단계의 req.body에서 확보됨
|
||||
if (clubId) {
|
||||
try {
|
||||
await averageService.calculateMemberAverageByClubSetting(memberId, clubId);
|
||||
} catch (e2) {
|
||||
console.error('에버리지 워밍업 실패(deleteEventScore):', e2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('에버리지 캐시 무효화 오류(deleteEventScore):', error);
|
||||
}
|
||||
|
||||
res.json({
|
||||
@@ -1131,6 +1159,12 @@ exports.deleteParticipantScores = async (req, res) => {
|
||||
});
|
||||
}
|
||||
|
||||
// 삭제 전 memberId 조회 (캐시 무효화용)
|
||||
const ep = await EventParticipant.findOne({
|
||||
where: { id: participantId },
|
||||
attributes: ['memberId']
|
||||
});
|
||||
|
||||
// 점수 삭제
|
||||
await EventScore.destroy({
|
||||
where: {
|
||||
@@ -1139,6 +1173,23 @@ exports.deleteParticipantScores = async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// 캐시 무효화: 해당 참가자의 회원 평균 캐시 제거 및 워밍업
|
||||
try {
|
||||
if (ep && ep.memberId) {
|
||||
await averageService.invalidateMemberAverageCache(ep.memberId);
|
||||
try {
|
||||
const ev = await Event.findOne({ where: { id: eventId }, attributes: ['clubId'] });
|
||||
if (ev && ev.clubId) {
|
||||
await averageService.calculateMemberAverageByClubSetting(ep.memberId, ev.clubId);
|
||||
}
|
||||
} catch (e2) {
|
||||
console.error('에버리지 워밍업 오류(deleteParticipantScores):', e2);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('에버리지 캐시 무효화 오류(deleteParticipantScores):', e);
|
||||
}
|
||||
|
||||
res.json({
|
||||
message: '점수가 삭제되었습니다.'
|
||||
});
|
||||
|
||||
@@ -718,6 +718,7 @@ exports.saveEventFileData = async (req, res) => {
|
||||
}
|
||||
|
||||
// 2. 참가자 및 점수 처리
|
||||
const affectedMemberIds = new Set();
|
||||
for (const participant of participants) {
|
||||
let eventParticipant;
|
||||
|
||||
@@ -754,15 +755,39 @@ exports.saveEventFileData = async (req, res) => {
|
||||
comment: ''
|
||||
}, { transaction: t });
|
||||
}
|
||||
affectedMemberIds.add(Number(participant.memberId));
|
||||
} else {
|
||||
// 새 회원 생성 및 참가자 등록
|
||||
// 클럽 여성 기본 핸디캡 기준으로 성별/핸디캡 보정
|
||||
const femaleBase = Number(clubInstance?.femaleHandicap ?? 0) || 0;
|
||||
let parsedHandicap = null;
|
||||
if (participant.handicap !== undefined && participant.handicap !== null) {
|
||||
const ph = Number(participant.handicap);
|
||||
if (Number.isFinite(ph)) parsedHandicap = ph;
|
||||
}
|
||||
// 점수 객체에 handicap이 개별 제공되는 경우 최댓값을 사용
|
||||
if (parsedHandicap == null && Array.isArray(participant.scores)) {
|
||||
for (const s of participant.scores) {
|
||||
if (s && typeof s === 'object' && s.handicap !== undefined) {
|
||||
const sh = Number(s.handicap);
|
||||
if (Number.isFinite(sh)) {
|
||||
parsedHandicap = parsedHandicap == null ? sh : Math.max(parsedHandicap, sh);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const isFemaleByRule = (parsedHandicap != null && parsedHandicap >= femaleBase) ||
|
||||
(Array.isArray(participant.scores) && participant.scores.some((s) => Number(s?.handicap) >= femaleBase));
|
||||
const genderNormalized = (participant.gender === 'female' || participant.gender === '여성') ? 'female' : 'male';
|
||||
const finalGender = isFemaleByRule ? 'female' : genderNormalized;
|
||||
|
||||
const newMember = await Member.create({
|
||||
clubId: effectiveClubId, // required by Member model
|
||||
name: participant.name,
|
||||
// normalize enum values to match Member model
|
||||
gender: (participant.gender === 'female' || participant.gender === '여성') ? 'female' : 'male',
|
||||
gender: finalGender,
|
||||
memberType: 'guest',
|
||||
status: 'active'
|
||||
status: 'active',
|
||||
handicap: parsedHandicap ?? 0
|
||||
}, { transaction: t });
|
||||
|
||||
// 클럽 회원으로 등록 (조인 테이블을 association으로 처리)
|
||||
@@ -788,6 +813,7 @@ exports.saveEventFileData = async (req, res) => {
|
||||
teamId: teamId,
|
||||
comment: ''
|
||||
}, { transaction: t });
|
||||
affectedMemberIds.add(Number(newMember.id));
|
||||
}
|
||||
|
||||
// 팀에 속한 참가자인 경우 팀 멤버로 등록
|
||||
@@ -857,20 +883,32 @@ exports.saveEventFileData = async (req, res) => {
|
||||
}
|
||||
}
|
||||
|
||||
return event;
|
||||
// 트랜잭션 내부에서는 목록만 반환 (커밋 후 워밍업)
|
||||
return { event, affectedMemberIds: Array.from(affectedMemberIds), effectiveClubId };
|
||||
});
|
||||
// 커밋 이후 평균 캐시 무효화 및 워밍업 (신규 점수가 커밋된 뒤 계산되도록)
|
||||
if (result && Array.isArray(result.affectedMemberIds)) {
|
||||
for (const mid of result.affectedMemberIds) {
|
||||
try {
|
||||
await averageService.invalidateMemberAverageCache(mid);
|
||||
await averageService.calculateMemberAverageByClubSetting(mid, result.effectiveClubId);
|
||||
} catch (e) {
|
||||
console.error('평균 캐시 갱신 실패:', e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.json({
|
||||
message: '이벤트 데이터가 성공적으로 저장되었습니다.',
|
||||
event: {
|
||||
id: result.id,
|
||||
title: result.title,
|
||||
eventType: result.eventType,
|
||||
startDate: result.startDate
|
||||
id: result.event.id,
|
||||
title: result.event.title,
|
||||
eventType: result.event.eventType,
|
||||
startDate: result.event.startDate
|
||||
},
|
||||
rollbackToken: {
|
||||
eventId: result.id,
|
||||
clubId: Number(result.clubId)
|
||||
eventId: result.event.id,
|
||||
clubId: Number(result.event.clubId)
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user