Skip to content
Snippets Groups Projects
Select Git revision
  • af05da72100f0da67c91b5891eccf44a42f92a91
  • master default protected
  • deploy
  • develop
4 results

schedule.test.js

Blame
  • eventController.js 9.02 KiB
    const Event = require('../models/Event');
    const EventParticipants = require('../models/EventParticipants');
    const {Op} = require('sequelize');
    const moment = require('moment'); // 날짜 포맷팅 라이브러리
    const UserEvent = require('../models/UserEvent.js');
    const {redisClient, capCheckLuaScript} = require("../datastore/redis");
    const UserCrew = require("../models/UserCrew");
    
    // 한 페이지당 기본 아이템 수
    const itemsPerPage = 10;
    
    const countKeyPattern = 'event:${eventID}:participant_count';
    
    // 이벤트 목록 조회 (단일 엔드포인트)
    exports.getEvents = async (req, res) => {
        console.log('이벤트 목록 조회 컨트롤러 실행'); // 로그 확인용
        try {
            const {sportTypeId, regionID, eventDate, page = 1} = req.query; // 쿼리 파라미터 가져오기
            const offset = (page - 1) * itemsPerPage; // 시작 지점 계산
    
            const where = {};
    
            // 쿼리 파라미터 조건 추가
            if (sportTypeId) where.sportTypeId = sportTypeId;
            if (regionID) where.regionID = regionID;
            if (eventDate) where.eventDate = eventDate;
    
            // 이벤트 데이터 가져오기
            const {rows: events, count: total} = await Event.findAndCountAll({
                where,
                limit: itemsPerPage,
                offset,
            });
    
            // 응답 데이터 반환
            res.status(200).json({
                events,
                total,          // 조건에 맞는 총 이벤트 개수
                itemsPerPage,   // 페이지당 이벤트 수
            });
        } catch (error) {
            console.error('이벤트 목록 조회 중 오류:', error);
            res.status(500).json({error: '이벤트 목록 조회 중 오류가 발생했습니다.'});
        }
    };
    
    // 이벤트 생성 컨트롤러
    exports.createEvent = async (req, res) => {
        try {
            const {
                crewID,
                regionID,
                name,
                sportTypeId,
                eventDate,
                capacity,
                feeCondition,
            } = req.body;
    
            const userID = req.user.userID;
    
            // TODO: 클라이언트에게 누락된 필드 정보를 명시적으로 전달하지 못하는 패턴입니다.
            // 추후 리팩터링 시 누락된 필드를 클라이언트에 명확히 알려주는 로직으로 개선할 필요가 있습니다.
            if (!regionID || !sportTypeId) {
                return res.status(400).json({error: '필수 필드가 누락되었습니다.'});
            }
    
            const newEvent = await Event.create({
                crewID,
                regionID,
                name,
                sportTypeId,
                eventDate,
                capacity,
                feeCondition,
                userID,
            });
    
            res.status(201).json(newEvent);
        } catch (error) {
            console.error('이벤트 생성 중 오류:', error);
            res.status(500).json({error: '이벤트 생성 중 오류가 발생했습니다.'});
        }
    };
    
    // 특정 이벤트 조회 컨트롤러
    exports.getEventById = async (req, res) => {
        try {
            const {eventID} = req.params;
    
            // 이벤트 정보 조회
            const event = await Event.findByPk(eventID, {
                attributes: [
                    'eventID',
                    'regionID',
                    'name',
                    'sportTypeId',
                    'eventDate',
                    'capacity',
                    'feeCondition',
                    'userID',
                    'createdDate',
                ],
            });
    
            if (!event) {
                return res.status(404).json({error: '해당 이벤트가 존재하지 않습니다.'});
            }
    
            // 현재 참여한 인원 수 계산
            const currentMemberCount = redisClient.get(countKeyPattern).then((result) => {
                return parseInt(result, 10);
            }).catch((error) => {
                console.error('이벤트 참여자 수 조회중 오류', error);
    
                return UserEvent.count({
                    where: {eventID: event.eventID},
                });
            });
    
            // 이벤트 데이터에 현재 참여한 인원 수 추가
            const response = {
                ...event.toJSON(),
                currentMemberCount, // 현재 참여한 인원 수
            };
    
            res.status(200).json(response);
        } catch (error) {
            console.error('이벤트 조회 중 오류:', error);
            res.status(500).json({error: '이벤트 조회 중 오류가 발생했습니다.'});
        }
    };
    
    
    // 이벤트 수정 컨트롤러
    exports.updateEvent = async (req, res) => {
        try {
            const {eventID} = req.params;
    
            const updateData = req.body;
    
            const userID = req.user.userID;
    
            const event = await Event.findByPk(eventID);
            if (!event) {
                return res.status(404).json({error: '해당 이벤트가 존재하지 않습니다.'});
            }
    
            if (event.userID !== userID) {
                return res.status(403).json({error: '이벤트 수정 권한이 없습니다.'});
            }
    
            await event.update(updateData);
    
            res.status(200).json({updatedEvent: event});
        } catch (error) {
            console.error('이벤트 수정 중 오류:', error);
            res.status(500).json({error: '이벤트 수정 중 오류가 발생했습니다.'});
        }
    };
    
    // 이벤트 삭제 컨트롤러
    exports.deleteEvent = async (req, res) => {
        try {
            const {eventID} = req.params;
    
            const userID = req.user.userID;
    
            const event = await Event.findByPk(eventID);
            if (!event) {
                return res.status(404).json({error: '해당 이벤트가 존재하지 않습니다.'});
            }
    
            if (event.userID !== userID) {
                return res.status(403).json({error: '이벤트 삭제 권한이 없습니다.'});
            }
    
            await event.destroy();
    
            res.status(200).json({message: '이벤트가 성공적으로 삭제되었습니다.'});
        } catch (error) {
            console.error('이벤트 삭제 중 오류:', error);
            res.status(500).json({error: '이벤트 삭제 중 오류가 발생했습니다.'});
        }
    };
    
    // 이벤트 참여 컨트롤러
    exports.participateEvent = async (req, res) => {
        const {eventID} = req.params;
    
        const userID = req.user.userID;
    
        if (!eventID || !userID) {
            return res.status(400).json({error: '필수 데이터가 누락되었습니다.'});
        }
    
        const event = await Event.findByPk(eventID);
        if (!event) {
            return res.status(404).json({error: '해당 이벤트가 존재하지 않습니다.'});
        }
    
        const existingParticipant = await EventParticipants.findOne({where: {eventID, userID}});
        if (existingParticipant) {
            return res.status(409).json({error: '이미 이벤트에 참여 중입니다.'});
        }
    
        const capacity = parseInt(event.capacity, 10);
    
        try {
            const result = await redisClient.sendCommand([
                'EVAL',
                capCheckLuaScript,
                '1',
                countKeyPattern,
                capacity.toString()
            ]);
    
            // 인원이 초과하지 않은 경우, 참여 진행.
            if (result === 1) {
                const newParticipant = await EventParticipants.create({
                    userID,
                    eventID,
                    participationDate: new Date(),
                    status: 'attending',
                });
    
                res.status(201).json(newParticipant);
            } else {
                return res.status(409).json({error: '이벤트의 최대 참여 인원 수를 초과했습니다.'});
            }
        } catch (error) {
            // 참여 실패시 가입 카운트를 감소시킴.
            await redisClient.decr(countKeyPattern);
    
            console.error('이벤트 참여 중 오류:', error);
    
            res.status(500).json({error: '이벤트 참여 중 오류가 발생했습니다.'});
        }
    };
    
    // 이벤트 참여 취소 컨트롤러
    exports.cancelParticipation = async (req, res) => {
        try {
            const {eventID} = req.params; // URL에서 eventID 가져오기
    
            const userID = req.user.userID;
    
            // 필수 데이터 검증
            if (!eventID || !userID) {
                return res.status(400).json({error: '필수 데이터가 누락되었습니다.'});
            }
    
            // 이벤트 존재 여부 확인
            const event = await Event.findByPk(eventID);
            if (!event) {
                return res.status(404).json({error: '해당 이벤트가 존재하지 않습니다.'});
            }
    
            // 참여 기록 확인
            const participant = await EventParticipants.findOne({where: {eventID, userID}});
            if (!participant) {
                return res.status(404).json({error: '참여 기록이 존재하지 않습니다.'});
            }
    
            // 상태 변경 (참여 취소)
            participant.status = 'canceled';
            await participant.save();
            // 참여 인원 카운트 감소
            await redisClient.decr(countKeyPattern);
    
            res.status(200).json({
                message: '이벤트 참여가 성공적으로 취소되었습니다.',
                participant,
            });
        } catch (error) {
            console.error('이벤트 참여 취소 중 오류:', error);
            res.status(500).json({error: '이벤트 참여 취소 중 오류가 발생했습니다.'});
        }
    };