/** * 이벤트 컨트롤러 * 이벤트 관련 기능을 처리하는 컨트롤러 */ const { Event, EventParticipant, Member, Club, EventScore, ClubMember, EventTeam, EventTeamMember } = 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, attributes: ['id', 'status', 'paymentStatus'], where: { status: { [Op.ne]: '취소' } }, required: false, 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, attributes: ['id', 'status', 'paymentStatus'], where: { status: { [Op.ne]: '취소' } }, required: false, include: [ { model: Member, attributes: ['id', 'name', 'average'] } ] } ] }); 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: startDate ? startDate : null, 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 ? startDate : event.startDate, endDate: 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, attributes: ['id', 'status'], where: { status: { [Op.ne]: '취소' } }, required: false } ] }); if (!updatedEvent) { return res.status(404).json({ message: '이벤트를 찾을 수 없습니다.' }); } 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, 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, 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, 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, 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, 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', 'average'] } ], 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, status, paymentStatus } = 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, status: status || '참가예정', paymentStatus: paymentStatus || '미납', createdAt: new Date(), updatedAt: 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.getEventTeams = async (req, res) => { try { const eventId = req.params.id; if (!eventId) { return res.status(400).json({ message: '이벤트 ID가 필요합니다.' }); } const teams = await EventTeam.findAll({ where: { eventId }, include: [ { model: EventTeamMember, include: [ { model: EventParticipant, include: [{ model: Member }] } ] } ], order: [['teamNumber', 'ASC']] }); const result = teams.map(team => ({ id: team.id, teamNumber: team.teamNumber, handicap: team.handicap, members: (team.EventTeamMembers || []) .sort((a, b) => a.order - b.order) .map(tm => ({ id: tm.eventParticipantId, name: tm.EventParticipant?.Member?.name || `참가자 ${tm.eventParticipantId}`, order: tm.order })) })); res.json({ teams: result }); } catch (error) { console.error('팀 목록 조회 오류:', error); res.status(500).json({ message: '팀 목록을 가져오는 중 오류가 발생했습니다.' }); } }; // [팀 생성 기능] 이벤트별 팀 배정 저장 exports.createOrUpdateEventTeams = async (req, res) => { const eventId = req.params.id; const { teams } = req.body; // [{teamNumber, handicap, members:[id]}] if (!eventId || !Array.isArray(teams)) { return res.status(400).json({ message: '이벤트 ID와 팀 정보가 필요합니다.' }); } try { await sequelize.transaction(async (t) => { // 기존 팀 및 팀멤버 데이터 삭제 await EventTeam.destroy({ where: { eventId }, transaction: t }); await EventTeamMember.destroy({ where: {}, // eventId로만 삭제하려면, eventTeamId로 팀 id 목록을 먼저 조회해서 삭제 transaction: t }); // 새 팀 및 팀멤버 데이터 저장 for (const team of teams) { // 팀 생성 const createdTeam = await EventTeam.create({ eventId, teamNumber: team.teamNumber, handicap: team.handicap || 0 }, { transaction: t }); // 팀 멤버(순서 포함) 저장 if (Array.isArray(team.members) && team.members.length > 0) { const teamMemberRows = team.members .filter(m => m.id != null) .map(m => ({ eventTeamId: createdTeam.id, eventParticipantId: m.id, order: m.order ?? 1 })); if (teamMemberRows.length > 0) { await EventTeamMember.bulkCreate(teamMemberRows, { transaction: t }); } } } }); res.json({ message: '팀 배정이 저장되었습니다.' }); } 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: '참가자 삭제 중 오류가 발생했습니다.' }); } };