1233 lines
31 KiB
JavaScript
1233 lines
31 KiB
JavaScript
/**
|
|
* 이벤트 컨트롤러
|
|
* 이벤트 관련 기능을 처리하는 컨트롤러
|
|
*/
|
|
const { Event, EventParticipant, Member, Club, EventScore, ClubMember } = require('../models');
|
|
const { Op } = require('sequelize');
|
|
const { sequelize } = require('../models');
|
|
|
|
// 이벤트 목록 조회
|
|
exports.getAllEvents = async (req, res) => {
|
|
try {
|
|
const { clubId } = req.body;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const events = await Event.findAll({
|
|
where: {
|
|
clubId,
|
|
status: { [Op.ne]: '삭제' }
|
|
},
|
|
include: [
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name']
|
|
},
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participants',
|
|
attributes: ['id', 'status', 'paymentStatus'],
|
|
where: {
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [{
|
|
model: Member,
|
|
attributes: ['id', 'name', 'memberType', 'gender']
|
|
}]
|
|
}
|
|
],
|
|
order: [['startDate', 'ASC']]
|
|
});
|
|
|
|
const formattedEvents = events.map(event => {
|
|
const eventData = event.toJSON();
|
|
return {
|
|
...eventData,
|
|
participantCount: eventData.participants ? eventData.participants.length : 0,
|
|
clubName: eventData.Club ? eventData.Club.name : ''
|
|
};
|
|
});
|
|
|
|
res.json(formattedEvents);
|
|
} catch (error) {
|
|
console.error('이벤트 목록 조회 오류:', error);
|
|
res.status(500).json({ message: '이벤트 목록을 가져오는 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 특정 이벤트 조회
|
|
exports.getEventById = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
|
|
if (!eventId) {
|
|
return res.status(400).json({ message: '이벤트 ID가 필요합니다.' });
|
|
}
|
|
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
status: { [Op.ne]: '삭제' }
|
|
},
|
|
include: [
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name', 'location']
|
|
},
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participants',
|
|
attributes: ['id', 'status', 'paymentStatus'],
|
|
where: {
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [{
|
|
model: Member,
|
|
attributes: ['id', 'name']
|
|
}]
|
|
}
|
|
]
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
const formattedEvent = {
|
|
...event.toJSON(),
|
|
participantCount: event.participants ? event.participants.length : 0,
|
|
clubName: event.Club ? event.Club.name : ''
|
|
};
|
|
|
|
res.json(formattedEvent);
|
|
} catch (error) {
|
|
console.error('이벤트 조회 오류:', error);
|
|
res.status(500).json({ message: '이벤트 정보를 가져오는 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 새 이벤트 생성
|
|
exports.createEvent = async (req, res) => {
|
|
try {
|
|
const {
|
|
clubId,
|
|
title,
|
|
description,
|
|
startDate,
|
|
endDate,
|
|
location,
|
|
maxParticipants,
|
|
eventType,
|
|
entryFee,
|
|
gameCount,
|
|
laneCount,
|
|
status
|
|
} = req.body;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const club = await Club.findOne({
|
|
where: {
|
|
id: clubId,
|
|
status: 'active'
|
|
}
|
|
});
|
|
|
|
if (!club) {
|
|
return res.status(404).json({ message: '클럽을 찾을 수 없습니다.' });
|
|
}
|
|
const endDateVal = endDate ? new Date(endDate) : null;
|
|
const event = await Event.create({
|
|
clubId,
|
|
title,
|
|
description,
|
|
startDate: new Date(startDate),
|
|
endDate: endDateVal,
|
|
location,
|
|
maxParticipants: maxParticipants || 0,
|
|
eventType: eventType || '일반',
|
|
entryFee: entryFee || 0,
|
|
gameCount: gameCount || 3,
|
|
laneCount: laneCount || 1,
|
|
status: status || '활성'
|
|
});
|
|
|
|
const createdEvent = await Event.findOne({
|
|
where: { id: event.id },
|
|
include: [
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name']
|
|
}
|
|
]
|
|
});
|
|
|
|
res.status(201).json({
|
|
message: '이벤트가 생성되었습니다.',
|
|
event: {
|
|
...createdEvent.toJSON(),
|
|
participantCount: 0,
|
|
clubName: createdEvent.Club ? createdEvent.Club.name : ''
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('이벤트 생성 오류:', error);
|
|
res.status(500).json({ message: '이벤트 생성 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 정보 업데이트
|
|
exports.updateEvent = async (req, res) => {
|
|
try {
|
|
const {
|
|
clubId,
|
|
title,
|
|
description,
|
|
startDate,
|
|
location,
|
|
maxParticipants,
|
|
eventType,
|
|
entryFee,
|
|
gameCount,
|
|
laneCount,
|
|
status
|
|
} = req.body;
|
|
const eventId = req.body.id;
|
|
let endDate = req.body.endDate;
|
|
if (!eventId || !clubId) {
|
|
return res.status(400).json({ message: '이벤트 ID와 클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
if(endDate == 'Invalid Date') {
|
|
endDate = null;
|
|
}
|
|
const updateData = {
|
|
title,
|
|
description,
|
|
startDate: startDate ? new Date(startDate) : event.startDate,
|
|
endDate: endDate ? new Date(endDate) : null,
|
|
location,
|
|
maxParticipants: maxParticipants || event.maxParticipants,
|
|
eventType: eventType || event.eventType,
|
|
entryFee: entryFee !== undefined ? entryFee : event.entryFee,
|
|
gameCount: gameCount || event.gameCount,
|
|
laneCount: laneCount || event.laneCount,
|
|
status: status || event.status
|
|
};
|
|
|
|
await event.update(updateData);
|
|
|
|
const updatedEvent = await Event.findOne({
|
|
where: { id: eventId },
|
|
include: [
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name']
|
|
},
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participants',
|
|
attributes: ['id', 'status'],
|
|
where: {
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
}
|
|
]
|
|
});
|
|
|
|
res.json({
|
|
message: '이벤트가 수정되었습니다.',
|
|
event: {
|
|
...updatedEvent.toJSON(),
|
|
participantCount: updatedEvent.participants ? updatedEvent.participants.length : 0,
|
|
clubName: updatedEvent.Club ? updatedEvent.Club.name : ''
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('이벤트 수정 오류:', error);
|
|
res.status(500).json({ message: '이벤트 수정 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 삭제 (소프트 삭제)
|
|
exports.deleteEvent = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
const { clubId } = req.body;
|
|
|
|
console.log(eventId, clubId, req.body, req.params);
|
|
if (!eventId || !clubId) {
|
|
return res.status(400).json({ message: '이벤트 ID와 클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
},
|
|
include: [
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name']
|
|
}
|
|
]
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 참가자 정보도 함께 삭제 처리
|
|
await EventParticipant.update(
|
|
{ status: '취소' },
|
|
{
|
|
where: {
|
|
eventId,
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
}
|
|
);
|
|
|
|
await event.update({ status: 'deleted' });
|
|
|
|
res.json({
|
|
message: '이벤트가 삭제되었습니다.',
|
|
event: {
|
|
id: event.id,
|
|
title: event.title,
|
|
clubId: event.clubId,
|
|
clubName: event.Club ? event.Club.name : ''
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('이벤트 삭제 오류:', error);
|
|
res.status(500).json({ message: '이벤트 삭제 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 점수 조회
|
|
exports.getEventScores = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
|
|
if (!eventId) {
|
|
return res.status(400).json({ message: '이벤트 ID가 필요합니다.' });
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
const scores = await EventScore.findAll({
|
|
where: { eventId },
|
|
include: [
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participant',
|
|
attributes: ['id', 'status'],
|
|
include: [{
|
|
model: Member,
|
|
attributes: ['id', 'name']
|
|
}]
|
|
}
|
|
],
|
|
order: [
|
|
['gameNumber', 'ASC'],
|
|
['score', 'DESC']
|
|
]
|
|
});
|
|
|
|
return res.status(200).json(scores);
|
|
} catch (error) {
|
|
console.error('점수 조회 오류:', error);
|
|
res.status(500).json({ message: '점수 조회 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 점수 등록
|
|
exports.addEventScore = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
const {
|
|
participantId,
|
|
gameNumber,
|
|
score,
|
|
handicap = 0
|
|
} = req.body;
|
|
|
|
if (!eventId || !participantId || !gameNumber || score === undefined) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID, 참가자 ID, 게임 번호, 점수가 필요합니다.'
|
|
});
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 참가자 확인
|
|
const participant = await EventParticipant.findOne({
|
|
where: {
|
|
id: participantId,
|
|
eventId,
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
});
|
|
|
|
if (!participant) {
|
|
return res.status(400).json({ message: '이벤트 참가자가 아닙니다.' });
|
|
}
|
|
|
|
// 게임 번호 유효성 검사
|
|
if (gameNumber < 1 || gameNumber > event.gameCount) {
|
|
return res.status(400).json({
|
|
message: `게임 번호는 1부터 ${event.gameCount}까지만 입력 가능합니다.`
|
|
});
|
|
}
|
|
|
|
// 점수 유효성 검사
|
|
if (score < 0 || score > 300) {
|
|
return res.status(400).json({
|
|
message: '점수는 0에서 300 사이여야 합니다.'
|
|
});
|
|
}
|
|
|
|
// 동일한 게임의 점수가 이미 있는지 확인
|
|
const existingScore = await EventScore.findOne({
|
|
where: {
|
|
eventId,
|
|
participantId,
|
|
gameNumber
|
|
}
|
|
});
|
|
|
|
if (existingScore) {
|
|
return res.status(400).json({
|
|
message: '해당 게임의 점수가 이미 등록되어 있습니다.'
|
|
});
|
|
}
|
|
|
|
// 점수 등록
|
|
const totalScore = score + handicap;
|
|
const newScore = await EventScore.create({
|
|
eventId,
|
|
participantId,
|
|
gameNumber,
|
|
score,
|
|
handicap,
|
|
totalScore
|
|
});
|
|
|
|
// 참가자 평균 점수 업데이트
|
|
const allScores = await EventScore.findAll({
|
|
where: {
|
|
eventId,
|
|
participantId
|
|
}
|
|
});
|
|
|
|
const totalGames = allScores.length;
|
|
const averageScore = Math.round(allScores.reduce((sum, s) => sum + s.score, 0) / totalGames);
|
|
|
|
await participant.update({
|
|
games: totalGames,
|
|
average: averageScore
|
|
});
|
|
|
|
res.status(201).json({
|
|
message: '점수가 등록되었습니다.',
|
|
score: {
|
|
id: newScore.id,
|
|
eventId: newScore.eventId,
|
|
participantId: newScore.participantId,
|
|
gameNumber: newScore.gameNumber,
|
|
score: newScore.score,
|
|
handicap: newScore.handicap,
|
|
totalScore: newScore.totalScore,
|
|
createdAt: newScore.createdAt
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('점수 등록 오류:', error);
|
|
res.status(500).json({ message: '점수 등록 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 점수 수정
|
|
exports.updateEventScore = async (req, res) => {
|
|
try {
|
|
const eventId = Number(req.params.id);
|
|
const scoreId = Number(req.params.scoreId);
|
|
const {
|
|
gameNumber,
|
|
score,
|
|
handicap = 0
|
|
} = req.body;
|
|
|
|
console.log('Updating score:', {
|
|
params: { eventId, scoreId },
|
|
body: { gameNumber, score, handicap }
|
|
});
|
|
|
|
if (!eventId || !scoreId || !gameNumber || score === undefined || score === null) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID, 점수 ID, 게임 번호, 점수가 필요합니다.',
|
|
received: { eventId, scoreId, gameNumber, score }
|
|
});
|
|
}
|
|
|
|
// 점수 레코드 확인
|
|
const scoreRecord = await EventScore.findOne({
|
|
where: {
|
|
id: scoreId,
|
|
eventId
|
|
}
|
|
});
|
|
|
|
// 점수 레코드가 없으면 참가자 ID를 가져와서 새로 생성
|
|
if (!scoreRecord) {
|
|
// 기존 점수에서 참가자 ID 가져오기
|
|
const existingScore = await EventScore.findOne({
|
|
where: { eventId },
|
|
order: [['createdAt', 'DESC']]
|
|
});
|
|
|
|
if (!existingScore) {
|
|
return res.status(404).json({
|
|
message: '참가자 정보를 찾을 수 없습니다.'
|
|
});
|
|
}
|
|
|
|
// 새로운 게임 점수 생성
|
|
const newScore = await EventScore.create({
|
|
eventId,
|
|
participantId: existingScore.participantId,
|
|
teamNumber: existingScore.teamNumber,
|
|
gameNumber,
|
|
score,
|
|
handicap,
|
|
totalScore: score + handicap
|
|
});
|
|
|
|
return res.json({
|
|
message: '새로운 게임 점수가 등록되었습니다.',
|
|
score: newScore
|
|
});
|
|
}
|
|
|
|
// 기존 레코드 업데이트
|
|
await scoreRecord.update({
|
|
gameNumber,
|
|
score,
|
|
handicap,
|
|
totalScore: score + handicap
|
|
});
|
|
|
|
// 업데이트된 레코드 조회
|
|
const updatedScore = await EventScore.findOne({
|
|
where: {
|
|
id: scoreId,
|
|
eventId
|
|
}
|
|
});
|
|
|
|
res.json({
|
|
message: '점수가 수정되었습니다.',
|
|
score: updatedScore
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('점수 수정 오류:', error);
|
|
res.status(500).json({
|
|
message: '점수 수정 중 오류가 발생했습니다.',
|
|
error: error.message
|
|
});
|
|
}
|
|
};
|
|
|
|
// 점수 삭제
|
|
exports.deleteEventScore = async (req, res) => {
|
|
try {
|
|
const { eventId, clubId, scoreId } = req.body;
|
|
|
|
if (!eventId || !clubId || !scoreId) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID, 클럽 ID, 점수 ID가 필요합니다.'
|
|
});
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 점수 존재 여부 확인
|
|
const score = await EventScore.findOne({
|
|
where: {
|
|
id: scoreId,
|
|
eventId
|
|
},
|
|
include: [
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participant',
|
|
attributes: ['id', 'status'],
|
|
include: [{
|
|
model: Member,
|
|
attributes: ['id', 'name']
|
|
}]
|
|
}
|
|
]
|
|
});
|
|
|
|
if (!score) {
|
|
return res.status(404).json({ message: '점수를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
await score.destroy();
|
|
|
|
res.json({
|
|
message: '점수가 삭제되었습니다.',
|
|
score: {
|
|
id: score.id,
|
|
userId: score.userId,
|
|
userName: score.participant.Member ? score.participant.Member.name : '알 수 없음',
|
|
gameNumber: score.gameNumber,
|
|
frameNumber: score.frameNumber
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('점수 삭제 오류:', error);
|
|
res.status(500).json({ message: '점수 삭제 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 참가자의 모든 점수 삭제
|
|
exports.deleteParticipantScores = async (req, res) => {
|
|
try {
|
|
const eventId = Number(req.params.id);
|
|
const participantId = Number(req.params.participantId);
|
|
|
|
if (!eventId || !participantId) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID와 참가자 ID가 필요합니다.'
|
|
});
|
|
}
|
|
|
|
// 점수 삭제
|
|
await EventScore.destroy({
|
|
where: {
|
|
eventId,
|
|
participantId
|
|
}
|
|
});
|
|
|
|
res.json({
|
|
message: '점수가 삭제되었습니다.'
|
|
});
|
|
} catch (error) {
|
|
console.error('점수 삭제 오류:', error);
|
|
res.status(500).json({
|
|
message: '점수 삭제 중 오류가 발생했습니다.'
|
|
});
|
|
}
|
|
};
|
|
|
|
// 이벤트 통계 조회
|
|
exports.getEventStats = async (req, res) => {
|
|
try {
|
|
const eventId = parseInt(req.params.id);
|
|
const { clubId } = req.query;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const stats = await EventScore.findAll({
|
|
where: { eventId },
|
|
attributes: [
|
|
'userId',
|
|
[sequelize.fn('AVG', sequelize.col('score')), 'averageScore'],
|
|
[sequelize.fn('MAX', sequelize.col('score')), 'highScore'],
|
|
[sequelize.fn('COUNT', sequelize.literal('CASE WHEN "isStrike" = true THEN 1 END')), 'strikeCount'],
|
|
[sequelize.fn('COUNT', sequelize.literal('CASE WHEN "isSpare" = true THEN 1 END')), 'spareCount']
|
|
],
|
|
include: [{
|
|
model: EventParticipant,
|
|
as: 'participant',
|
|
attributes: [],
|
|
include: [{
|
|
model: Member,
|
|
attributes: ['name']
|
|
}]
|
|
}],
|
|
group: ['userId', 'participant.id', 'participant.Member.id', 'participant.Member.name']
|
|
});
|
|
|
|
res.json(stats);
|
|
} catch (error) {
|
|
console.error('통계 조회 오류:', error);
|
|
res.status(500).json({ message: '통계 조회 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 캘린더용 이벤트 조회
|
|
exports.getCalendarEvents = async (req, res) => {
|
|
try {
|
|
const { clubId } = req.query;
|
|
const { start, end } = req.query;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const where = {
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
};
|
|
|
|
if (start && end) {
|
|
where.startDate = {
|
|
[Op.between]: [new Date(start), new Date(end)]
|
|
};
|
|
}
|
|
|
|
const events = await Event.findAll({
|
|
where,
|
|
attributes: [
|
|
'id',
|
|
'title',
|
|
'description',
|
|
'startDate',
|
|
'endDate',
|
|
'location',
|
|
'eventType',
|
|
'status'
|
|
],
|
|
order: [['startDate', 'ASC']]
|
|
});
|
|
|
|
const calendarEvents = events.map(event => ({
|
|
id: event.id,
|
|
title: event.title,
|
|
start: event.startDate,
|
|
end: event.endDate,
|
|
description: event.description,
|
|
location: event.location,
|
|
eventType: event.eventType,
|
|
status: event.status
|
|
}));
|
|
|
|
res.json(calendarEvents);
|
|
} catch (error) {
|
|
console.error('캘린더 이벤트 조회 오류:', error);
|
|
res.status(500).json({ message: '캘린더 이벤트 조회 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 참가 신청
|
|
exports.registerForEvent = async (req, res) => {
|
|
try {
|
|
const eventId = parseInt(req.params.id);
|
|
const { clubId } = req.query;
|
|
const { userId, teamNumber } = req.body;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 이미 등록된 참가자인지 확인
|
|
const existingParticipant = await EventParticipant.findOne({
|
|
where: {
|
|
eventId,
|
|
userId,
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
});
|
|
|
|
if (existingParticipant) {
|
|
return res.status(400).json({ message: '이미 등록된 참가자입니다.' });
|
|
}
|
|
|
|
const participant = await EventParticipant.create({
|
|
eventId,
|
|
userId,
|
|
teamNumber,
|
|
status: 'registered',
|
|
registeredAt: new Date()
|
|
});
|
|
|
|
res.status(201).json(participant);
|
|
} catch (error) {
|
|
console.error('참가 신청 오류:', error);
|
|
res.status(500).json({ message: '참가 신청 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 참가자 제거
|
|
exports.removeParticipant = async (req, res) => {
|
|
try {
|
|
const { id: eventId, userId } = req.params;
|
|
const { clubId } = req.query;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const participant = await EventParticipant.findOne({
|
|
where: {
|
|
eventId,
|
|
userId,
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [{
|
|
model: Event,
|
|
where: {
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
}]
|
|
});
|
|
|
|
if (!participant) {
|
|
return res.status(404).json({ message: '참가자를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
await participant.update({ status: '취소' });
|
|
res.json({ message: '참가자가 제거되었습니다.' });
|
|
} catch (error) {
|
|
console.error('참가자 제거 오류:', error);
|
|
res.status(500).json({ message: '참가자 제거 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 참가자 상태 업데이트
|
|
exports.updateParticipantStatus = async (req, res) => {
|
|
try {
|
|
const { id: eventId, userId } = req.params;
|
|
const { clubId } = req.query;
|
|
const { status, attendance, paymentStatus, paymentAmount } = req.body;
|
|
|
|
if (!clubId) {
|
|
return res.status(400).json({ message: '클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
const participant = await EventParticipant.findOne({
|
|
where: {
|
|
eventId,
|
|
userId,
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [{
|
|
model: Event,
|
|
where: {
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
}]
|
|
});
|
|
|
|
if (!participant) {
|
|
return res.status(404).json({ message: '참가자를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
await participant.update({
|
|
status,
|
|
attendance,
|
|
paymentStatus,
|
|
paymentAmount
|
|
});
|
|
|
|
res.json(participant);
|
|
} catch (error) {
|
|
console.error('참가자 상태 업데이트 오류:', error);
|
|
res.status(500).json({ message: '참가자 상태 업데이트 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 클럽별 이벤트 조회
|
|
exports.getEventsByClub = async (req, res) => {
|
|
try {
|
|
const clubId = parseInt(req.params.clubId);
|
|
|
|
const events = await Event.findAll({
|
|
where: {
|
|
clubId,
|
|
status: 'active'
|
|
},
|
|
order: [['startDate', 'ASC']]
|
|
});
|
|
|
|
res.json(events);
|
|
} catch (error) {
|
|
console.error('클럽별 이벤트 조회 오류:', error);
|
|
res.status(500).json({ message: '클럽별 이벤트 목록을 가져오는 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 사용자별 참가 이벤트 조회
|
|
exports.getUserEvents = async (req, res) => {
|
|
try {
|
|
const userId = req.user.id;
|
|
|
|
const events = await Event.findAll({
|
|
include: [
|
|
{
|
|
model: EventParticipant,
|
|
as: 'participants',
|
|
where: { userId },
|
|
attributes: []
|
|
},
|
|
{
|
|
model: Club,
|
|
attributes: ['id', 'name']
|
|
}
|
|
],
|
|
order: [['startDate', 'ASC']]
|
|
});
|
|
|
|
res.json(events);
|
|
} catch (error) {
|
|
console.error('사용자별 이벤트 조회 오류:', error);
|
|
res.status(500).json({ message: '사용자별 이벤트 목록을 가져오는 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 참가자 목록 조회
|
|
exports.getEventParticipants = async (req, res) => {
|
|
try {
|
|
const { eventId, clubId } = req.body;
|
|
|
|
if (!eventId || !clubId) {
|
|
return res.status(400).json({ message: '이벤트 ID와 클럽 ID가 필요합니다.' });
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
const participants = await EventParticipant.findAll({
|
|
where: {
|
|
eventId,
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [
|
|
{
|
|
model: Member,
|
|
attributes: ['id', 'name', 'email', 'phone', 'memberType']
|
|
}
|
|
],
|
|
order: [
|
|
['createdAt', 'ASC']
|
|
]
|
|
});
|
|
|
|
const formattedParticipants = participants.map(participant => ({
|
|
...participant.toJSON(),
|
|
}));
|
|
|
|
res.json({
|
|
message: '참가자 목록 조회가 완료되었습니다.',
|
|
participants: formattedParticipants
|
|
});
|
|
} catch (error) {
|
|
console.error('참가자 목록 조회 오류:', error);
|
|
res.status(500).json({ message: '참가자 목록을 가져오는 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 이벤트 참가자 등록
|
|
exports.addEventParticipant = async (req, res) => {
|
|
try {
|
|
const {
|
|
clubId,
|
|
memberId,
|
|
teamNumber,
|
|
paymentStatus,
|
|
paymentAmount
|
|
} = req.body;
|
|
const eventId = req.params.id;
|
|
if (!eventId || !clubId || !memberId) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID, 클럽 ID, 사용자 ID가 필요합니다.'
|
|
});
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 클럽 회원 확인
|
|
const member = await Member.findOne({
|
|
where: {
|
|
id: memberId,
|
|
clubId,
|
|
status: 'active'
|
|
}
|
|
});
|
|
|
|
if (!member) {
|
|
return res.status(400).json({ message: '클럽 회원이 아닙니다.' });
|
|
}
|
|
|
|
// 이미 참가 신청했는지 확인
|
|
const existingParticipant = await EventParticipant.findOne({
|
|
where: {
|
|
eventId,
|
|
memberId,
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
});
|
|
|
|
if (existingParticipant) {
|
|
return res.status(400).json({ message: '이미 참가 신청한 사용자입니다.' });
|
|
}
|
|
|
|
// 참가자 수 제한 확인
|
|
if (event.maxParticipants > 0) {
|
|
const currentParticipants = await EventParticipant.count({
|
|
where: {
|
|
eventId,
|
|
status: { [Op.ne]: '취소' }
|
|
}
|
|
});
|
|
|
|
if (currentParticipants >= event.maxParticipants) {
|
|
return res.status(400).json({ message: '참가자 수가 초과되었습니다.' });
|
|
}
|
|
}
|
|
|
|
const participant = await EventParticipant.create({
|
|
eventId,
|
|
memberId,
|
|
teamNumber: teamNumber || 1,
|
|
status: req.body.status || '참가예정',
|
|
attendance: false,
|
|
paymentStatus: req.body.paymentStatus || '미납',
|
|
paymentAmount: paymentAmount || event.entryFee || 0,
|
|
registeredAt: new Date()
|
|
});
|
|
|
|
// 참가자 정보 조회
|
|
const participantWithDetails = await EventParticipant.findOne({
|
|
where: { id: participant.id },
|
|
include: [
|
|
{
|
|
model: Member,
|
|
attributes: ['id', 'name']
|
|
}
|
|
]
|
|
});
|
|
|
|
res.status(201).json({
|
|
message: '참가자가 등록되었습니다.',
|
|
participant: participantWithDetails
|
|
});
|
|
} catch (error) {
|
|
console.error('참가자 등록 오류:', error);
|
|
res.status(500).json({ message: '참가자 등록 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 참가자 정보 수정
|
|
exports.updateEventParticipant = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
const { id, clubId, memberId, status, paymentStatus } = req.body;
|
|
|
|
if (!eventId || !clubId || !memberId || !id) {
|
|
return res.status(400).json({ message: '이벤트 ID, 클럽 ID, 사용자 ID가 필요합니다.' });
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
clubId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 참가자 정보 수정
|
|
const [updatedCount] = await EventParticipant.update(
|
|
{ status, paymentStatus },
|
|
{
|
|
where: {
|
|
id,
|
|
eventId,
|
|
memberId
|
|
}
|
|
}
|
|
);
|
|
|
|
if (updatedCount === 0) {
|
|
return res.status(404).json({ message: '수정할 참가자 정보를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 수정된 참가자 정보 조회
|
|
const updatedParticipant = await EventParticipant.findOne({
|
|
where: { id },
|
|
include: [
|
|
{
|
|
model: Member,
|
|
attributes: ['id', 'name', 'email', 'phone', 'memberType']
|
|
}
|
|
]
|
|
});
|
|
|
|
res.json({
|
|
message: '참가자 정보가 수정되었습니다.',
|
|
participant: {
|
|
...updatedParticipant.toJSON(),
|
|
userName: updatedParticipant.Member ? updatedParticipant.Member.name : '알 수 없음',
|
|
userEmail: updatedParticipant.Member ? updatedParticipant.Member.email : '',
|
|
userPhone: updatedParticipant.Member ? updatedParticipant.Member.phone : '',
|
|
userType: updatedParticipant.Member ? updatedParticipant.Member.memberType : ''
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('참가자 정보 수정 오류:', error);
|
|
res.status(500).json({ message: '참가자 정보 수정 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|
|
|
|
// 참가자 삭제 (소프트 삭제)
|
|
exports.deleteEventParticipant = async (req, res) => {
|
|
try {
|
|
const eventId = req.params.id;
|
|
const { id } = req.body;
|
|
|
|
if (!eventId || !id) {
|
|
return res.status(400).json({
|
|
message: '이벤트 ID, 참가자 ID가 필요합니다.'
|
|
});
|
|
}
|
|
|
|
// 이벤트 존재 여부 확인
|
|
const event = await Event.findOne({
|
|
where: {
|
|
id: eventId,
|
|
status: { [Op.ne]: 'deleted' }
|
|
}
|
|
});
|
|
|
|
if (!event) {
|
|
return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 참가자 존재 여부 확인
|
|
const participant = await EventParticipant.findOne({
|
|
where: {
|
|
eventId,
|
|
id,
|
|
status: { [Op.ne]: '취소' }
|
|
},
|
|
include: [
|
|
{
|
|
model: Member,
|
|
attributes: ['id', 'name', 'memberType']
|
|
}
|
|
]
|
|
});
|
|
|
|
if (!participant) {
|
|
return res.status(404).json({ message: '참가자를 찾을 수 없습니다.' });
|
|
}
|
|
|
|
// 참가자의 점수도 함께 삭제
|
|
await EventScore.destroy({
|
|
where: {
|
|
eventId,
|
|
participantId: id
|
|
}
|
|
});
|
|
|
|
await participant.update({ status: '취소' });
|
|
|
|
res.json({
|
|
message: '참가자가 삭제되었습니다.',
|
|
participant: {
|
|
id: participant.id
|
|
}
|
|
});
|
|
} catch (error) {
|
|
console.error('참가자 삭제 오류:', error);
|
|
res.status(500).json({ message: '참가자 삭제 중 오류가 발생했습니다.' });
|
|
}
|
|
};
|