Skip to content
Snippets Groups Projects
Commit 2a507ad5 authored by 심재엽's avatar 심재엽
Browse files

Merge remote-tracking branch 'origin/develop' into feature/#12

parents 72516146 40950690
No related branches found
No related tags found
2 merge requests!31Develop,!25[#17] 채팅 푸시알림 추가
Showing
with 335 additions and 234 deletions
// src/config/sequelize.js
// config/sequelize.js
const { Sequelize } = require('sequelize');
require('dotenv').config();
const isTest = process.env.NODE_ENV === 'test';
const sequelize = isTest
? new Sequelize('sqlite::memory:', { logging: false }) // 테스트 환경용 인메모리 DB
? new Sequelize({
dialect: 'sqlite',
storage: ':memory:',
logging: false,
}) // 테스트 환경용 인메모리 DB
: new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: process.env.DB_HOST,
dialect: 'mysql',
logging: false,
dialect: 'mysql',
logging: false,
});
module.exports = sequelize;
\ No newline at end of file
module.exports = sequelize;
......@@ -4,9 +4,6 @@ class friendController {
/**
* 친구 요청 보내기
* 클라이언트는 userId와 요청을 보낼 사용자의 email을 전송
* @param {Object} req - Express 요청 객체
* @param {Object} res - Express 응답 객체
* @param {Function} next - Express next 미들웨어 함수
*/
async sendFriendRequest(req, res, next) {
const { userId, email } = req.body;
......@@ -140,13 +137,12 @@ class friendController {
/**
* 친구 목록 조회
* GET /api/friend/all
* GET /api/friend/all/:offset
*/
async getFriendList(req, res) {
try {
const userId = req.user.id;
const friends = await FriendService.getFriendList(userId);
const friends = await FriendService.getFriendList(userId,20,req.param);
return res.status(200).json({
success: true,
data: friends
......
// controllers/meetingController.js
const MeetingService = require('../services/meetingService');
const CreateMeetingRequestDTO = require('../dtos/CreateMeetingRequestDTO');
......@@ -7,13 +6,25 @@ class MeetingController {
/**
* 번개 모임 생성
* POST /api/meetings
*
* 프론트엔드 입력 데이터 형식 예시:
* {
* "title": "팀 동기화 미팅",
* "description": "월간 팀 동기화 회의입니다.",
* "time_idx_start": 40, // 예: 10:00 AM
* "time_idx_end": 42, // 예: 10:30 AM
* "location": "회의실 A",
* "deadline": "2024-04-25T23:59:59Z",
* "type": "OPEN" // "OPEN" 또는 "CLOSE"
* }
*/
async createMeeting(req, res) {
try {
const userId = req.userId; // 인증 미들웨어를 통해 설정된 사용자 ID
const meetingData = { ...req.body, created_by: userId };
// CreateMeetingRequestDTO를 사용하여 요청 데이터 검증
const userId = req.user.id;
const meetingData = {
...req.body,
created_by: userId
};
const createMeetingDTO = new CreateMeetingRequestDTO(meetingData);
createMeetingDTO.validate();
......@@ -31,8 +42,7 @@ class MeetingController {
*/
async getMeetings(req, res) {
try {
const userId = req.userId; // 인증 미들웨어를 통해 설정된 사용자 ID
const userId = req.user.id; // 인증 미들웨어를 통해 설정된 사용자 ID
const meetings = await MeetingService.getMeetings(userId);
res.status(200).json(meetings);
} catch (err) {
......@@ -43,11 +53,10 @@ class MeetingController {
/**
* 번개 모임 마감
* PATCH /api/meetings/:meetingId/close
* PATCH /api/meetings/:meetingId/close (URL 파라미터로 meetingId 전달)
*/
async closeMeeting(req, res) {
const { meetingId } = req.params;
try {
const meeting = await MeetingService.closeMeeting(meetingId);
res.status(200).json({ message: '모임이 마감되었습니다.', meeting });
......@@ -60,13 +69,15 @@ class MeetingController {
/**
* 번개 모임 참가
* POST /api/meetings/:meetingId/join
* (URL 파라미터로 meetingId 전달)
*/
async joinMeeting(req, res) {
try {
const { meetingId } = req.params;
const userId = req.userId; // 인증 미들웨어를 통해 설정된 사용자 ID
const userId = req.user.id; // 인증 미들웨어를 통해 설정된 사용자 ID
await MeetingService.joinMeeting(meetingId, userId);
res.status(200).json({ message: '모임 및 채팅방 참가 완료' });
} catch (err) {
console.error('모임 참가 오류:', err);
......@@ -77,10 +88,10 @@ class MeetingController {
/**
* 번개 모임 상세 조회
* GET /api/meetings/:meetingId
(URL 파라미터로 meetingId 전달)
*/
async getMeetingDetail(req, res) {
const { meetingId } = req.params;
try {
const meetingDetail = await MeetingService.getMeetingDetail(meetingId);
res.status(200).json(meetingDetail);
......
......@@ -6,28 +6,46 @@ class scheduleController {
/**
* 스케줄 생성
* POST /api/schedule
* 해당 사용자 id는 auth 미들웨어에서 설정된 사용자 정보 이용
* req.user = User 모델의 인스턴스
* 요청 본문 예시:
* {
* title: 'Schedule Title',
* is_fixed: true,
* events: [
* { time_idx: 36 },
* { time_idx: 37 },
* // ...
* ]
* }
*/
async createSchedule(req, res) {
try {
const userId = req.user.id;
const scheduleRequestDTO = new ScheduleRequestDTO(req.body);
const validatedData = scheduleRequestDTO.validate('create');
const validatedData = scheduleRequestDTO.validate('create'); // 'create' 타입 검증
const scheduleDTO = await ScheduleService.createSchedule({
const { title, is_fixed, events } = validatedData;
const schedules = await ScheduleService.createSchedules({
userId,
...validatedData
title,
is_fixed,
events
});
return res.status(201).json({
success: true,
data: scheduleDTO
data: {
schedules
}
});
} catch (error) {
return res.status(400).json({
success: false,
error: {
message: error.message.includes('Validation error') ? error.message : 'SCHEDULE_CREATE_ERROR',
code: error.message.includes('Validation error') ? 'VALIDATION_ERROR' : 'SCHEDULE_CREATE_ERROR'
message: error.message,
code: 'SCHEDULE_CREATE_ERROR'
}
});
}
......@@ -35,23 +53,35 @@ class scheduleController {
/**
* 스케줄 수정
* PUT /api/schedule/:id
* PUT /api/schedule
* Bulk update 지원
* 요청 본문 예시:
* {
* updates: [
* { time_idx: 36, title: 'New Title', is_fixed: true },
* { time_idx: 44, title: 'Another Title' },
* // ...
* ]
* }
*/
async updateSchedule(req, res) {
async updateSchedules(req, res) {
try {
const { id } = req.params;
const userId = req.user.id;
const scheduleRequestDTO = new ScheduleRequestDTO(req.body);
const validatedData = scheduleRequestDTO.validate('update');
const validatedData = scheduleRequestDTO.validate('bulk_update'); // 'bulk_update' 타입 검증
const { updates } = validatedData;
const scheduleDTO = await ScheduleService.updateSchedule(id, userId, validatedData);
const updatedSchedules = await ScheduleService.updateSchedules(userId, updates);
return res.status(200).json({
success: true,
data: scheduleDTO
data: {
schedules: updatedSchedules
}
});
} catch (error) {
if (error.message === 'Schedule not found') {
if (error.code === 'SCHEDULE_NOT_FOUND') {
return res.status(404).json({
success: false,
error: {
......@@ -59,14 +89,6 @@ class scheduleController {
code: 'SCHEDULE_NOT_FOUND'
}
});
} else if (error.message.includes('Validation error')) {
return res.status(400).json({
success: false,
error: {
message: error.message,
code: 'VALIDATION_ERROR'
}
});
}
return res.status(400).json({
success: false,
......@@ -80,34 +102,36 @@ class scheduleController {
/**
* 스케줄 삭제
* DELETE /api/schedule/:id
* DELETE /api/schedule
* Bulk delete 지원
* 요청 본문 예시:
* {
* time_idxs: [36, 44, ...]
* }
*/
async deleteSchedule(req, res) {
async deleteSchedules(req, res) {
try {
const { id } = req.params;
const userId = req.user.id;
const scheduleRequestDTO = new ScheduleRequestDTO(req.body);
const validatedData = scheduleRequestDTO.validate('bulk_delete'); // 'bulk_delete' 타입 검증
const { time_idxs } = validatedData;
const deleteResult = await ScheduleService.deleteSchedule(id, userId);
const result = await ScheduleService.deleteSchedules(userId, time_idxs);
return res.status(200).json({
success: true,
data: deleteResult
data: {
message: 'Schedules successfully deleted',
deleted_time_idxs: result.deleted_time_idxs
}
});
} catch (error) {
if (error.message === 'Schedule not found') {
return res.status(404).json({
success: false,
error: {
message: error.message,
code: 'SCHEDULE_NOT_FOUND'
}
});
}
return res.status(500).json({
return res.status(404).json({
success: false,
error: {
message: 'Failed to delete schedule',
code: 'DELETE_ERROR'
message: error.message,
code: 'SCHEDULE_DELETE_ERROR'
}
});
}
......@@ -120,11 +144,11 @@ class scheduleController {
async getAllSchedules(req, res) {
try {
const userId = req.user.id;
const schedulesDTO = await ScheduleService.getAllSchedules(userId);
const schedules = await ScheduleService.getAllSchedules(userId);
return res.status(200).json({
success: true,
data: schedulesDTO
data: schedules
});
} catch (error) {
return res.status(500).json({
......@@ -139,17 +163,19 @@ class scheduleController {
/**
* 해당 사용자 특정 스케줄 조회
* GET /api/schedule/:id
* GET /api/schedule/:time_idx
* 예: GET /api/schedule/36
*/
async getScheduleById(req, res) {
async getScheduleByTimeIdx(req, res) {
try {
const { id } = req.params;
const { time_idx } = req.params;
const userId = req.user.id;
const scheduleDTO = await ScheduleService.getScheduleById(id, userId);
const schedule = await ScheduleService.getScheduleByTimeIdx(userId, parseInt(time_idx, 10));
return res.status(200).json({
success: true,
data: scheduleDTO
data: schedule
});
} catch (error) {
if (error.message === 'Schedule not found') {
......
// dtos/CreateMeetingRequestDTO.js
const Joi = require('joi');
class CreateMeetingRequestDTO {
constructor({ title, description, start_time, end_time, location, deadline, type, created_by }) {
this.title = title;
this.description = description;
this.start_time = start_time;
this.end_time = end_time;
this.location = location;
this.deadline = deadline;
this.type = type;
this.created_by = created_by;
constructor({ title, description, time_idx_start, time_idx_end, location, time_idx_deadline, type, created_by }) {
this.data = {
title,
description,
time_idx_start,
time_idx_end,
location,
time_idx_deadline,
type,
created_by,
};
}
validate() {
const schema = Joi.object({
title: Joi.string().min(1).max(255).required(),
description: Joi.string().allow('', null).optional(),
start_time: Joi.date().iso().required(),
end_time: Joi.date().iso().greater(Joi.ref('start_time')).required(),
time_idx_start: Joi.number().integer().min(0).required(),
time_idx_end: Joi.number().integer().greater(Joi.ref('time_idx_start')).required(),
location: Joi.string().allow('', null).optional(),
deadline: Joi.date().iso().greater(Joi.ref('start_time')).optional(),
time_idx_deadline: Joi.number().integer().min(0).less(Joi.ref('time_idx_start')).optional(),
type: Joi.string().valid('OPEN', 'CLOSE').required(),
created_by: Joi.number().integer().positive().required()
created_by: Joi.number().integer().positive().required(),
});
const { error } = schema.validate(this, { abortEarly: false });
const { error } = schema.validate(this.data, { abortEarly: false });
if (error) {
const errorMessages = error.details.map(detail => detail.message).join(', ');
const errorMessages = error.details.map((detail) => detail.message).join(', ');
throw new Error(`Validation error: ${errorMessages}`);
}
......
// dto/FriendListDTO.js
class FriendListDTO {
/**
* @param {object} friend - Friend relationship object retrieved from the database.
* @param {number} userId - The ID of the user whose friend list is being retrieved.
*/
constructor(friend, userId) {
this.id = friend.id;
this.status = friend.status;
......
// dto/FriendRequestDTO.js
// dto/FriendResponseDTO.js
class FriendRequestDTO {
/**
* @param {object} friendRequest - Friend request object retrieved from the database.
*/
constructor(friendRequest) {
this.id = friendRequest.id;
class FriendResponseDTO {
constructor(friendResponse) {
this.id = friendResponse.id;
this.requester = {
id: friendRequest.requester.id,
name: friendRequest.requester.name,
email: friendRequest.requester.email
id: friendResponse.requester.id,
name: friendResponse.requester.name,
email: friendResponse.requester.email
};
this.receiver = {
id: friendRequest.receiver.id,
name: friendRequest.receiver.name,
email: friendRequest.receiver.email
id: friendResponse.receiver.id,
name: friendResponse.receiver.name,
email: friendResponse.receiver.email
};
this.status = friendRequest.status;
this.createdAt = friendRequest.createdAt;
this.updatedAt = friendRequest.updatedAt;
this.status = friendResponse.status;
this.createdAt = friendResponse.createdAt;
this.updatedAt = friendResponse.updatedAt;
}
}
module.exports = FriendRequestDTO;
module.exports = FriendResponseDTO;
// dtos/MeetingDetailResponseDTO.js
// dtos/MeetingResponseDTO.js
class MeetingDetailResponseDTO {
constructor(meeting) {
this.id = meeting.id;
this.title = meeting.title;
this.description = meeting.description;
this.startTime = meeting.start_time;
this.endTime = meeting.end_time;
this.timeIdxStart = meeting.time_idx_start;
this.timeIdxEnd = meeting.time_idx_end;
this.location = meeting.location;
this.deadline = meeting.deadline;
this.time_idx_deadline = meeting.time_idx_deadline;
this.type = meeting.type;
this.creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
this.participants = meeting.participants.map(participant => ({
......@@ -19,4 +18,4 @@ class MeetingDetailResponseDTO {
}
}
module.exports = MeetingDetailResponseDTO;
module.exports = MeetingDetailResponseDTO;
\ No newline at end of file
// dtos/MeetingResponseDTO.js
// dtos/MeetingDetailResponseDTO.js
class MeetingResponseDTO {
constructor(meeting, isParticipant, isScheduleConflict, creatorName) {
this.id = meeting.id;
this.title = meeting.title;
this.description = meeting.description;
this.startTime = meeting.start_time;
this.endTime = meeting.end_time;
this.timeIdxStart = meeting.time_idx_start;
this.timeIdxEnd = meeting.time_idx_end;
this.location = meeting.location;
this.deadline = meeting.deadline;
this.time_idx_deadline = meeting.time_idx_deadline;
this.type = meeting.type;
this.creatorName = creatorName;
this.isParticipant = isParticipant;
......@@ -16,4 +17,4 @@ class MeetingResponseDTO {
}
}
module.exports = MeetingResponseDTO;
module.exports = MeetingResponseDTO;
\ No newline at end of file
// dtos/ScheduleRequestDTO.js
const Joi = require('joi');
class ScheduleRequestDTO {
constructor(data) {
this.data = data;
}
validate(type = 'create') {
// 기본 스키마 정의
let schema = Joi.object({
title: Joi.string().min(1).max(255).required(),
start_time: Joi.date().iso().required(),
end_time: Joi.date().iso().required(),
is_fixed: Joi.boolean().required()
});
let schema;
// 'update' 타입의 경우 모든 필드를 필수로 하지 않을 수 있음
if (type === 'update') {
if (type === 'create') {
schema = Joi.object({
title: Joi.string().min(1).max(255).required(),
is_fixed: Joi.boolean().required(),
events: Joi.array().items(
Joi.object({
time_idx: Joi.number().integer().min(0).max(671).required(),
})
).min(1).required()
});
} else if (type === 'bulk_update') {
schema = Joi.object({
updates: Joi.array().items(
Joi.object({
time_idx: Joi.number().integer().min(0).max(671).required(),
title: Joi.string().min(1).max(255).optional(),
is_fixed: Joi.boolean().optional(),
})
).min(1).required()
});
} else if (type === 'bulk_delete') {
schema = Joi.object({
title: Joi.string().min(1).max(255).optional(),
start_time: Joi.date().iso().optional(),
end_time: Joi.date().iso().optional(),
is_fixed: Joi.boolean().optional()
}).or('title', 'start_time', 'end_time', 'is_fixed'); // 최소 한 개 이상의 필드가 필요
time_idxs: Joi.array().items(
Joi.number().integer().min(0).max(671).required()
).min(1).required()
});
}
const { error, value } = schema.validate(this.data, { abortEarly: false });
if (error) {
// 모든 에러 메시지를 하나의 문자열로 결합
const errorMessages = error.details.map(detail => detail.message).join(', ');
throw new Error(`Validation error: ${errorMessages}`);
}
// 검증된 데이터를 반환
return value;
}
}
......
......@@ -3,12 +3,10 @@
class ScheduleResponseDTO {
constructor(schedule) {
this.id = schedule.id;
this.user_id = schedule.user_id;
this.user_id = schedule.user_id;
this.title = schedule.title;
this.start_time = schedule.start_time;
this.end_time = schedule.end_time;
this.time_idx = schedule.time_idx; // 새로운 time_idx 필드 추가
this.is_fixed = schedule.is_fixed;
this.expiry_date = schedule.expiry_date;
this.createdAt = schedule.createdAt;
this.updatedAt = schedule.updatedAt;
}
......
// middlewares/auth.js
exports.isLoggedIn = (req, res, next) => {
exports.isLoggedIn = (req, res, next) => { //로그인된 사용자자만 접근허용
if (req.isAuthenticated()) {
return next();
}
res.redirect('/auth/login');
};
exports.isNotLoggedIn = (req, res, next) => {
exports.isNotLoggedIn = (req, res, next) => { //로그인 안되면 리다이렉트
if (!req.isAuthenticated()) {
return next();
}
......
......@@ -2,7 +2,7 @@
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');
const User = require('./User');
const User = require('./user');
const Friend = sequelize.define('Friend', {
status: {
......@@ -25,11 +25,4 @@ const Friend = sequelize.define('Friend', {
]
});
// 관계 설정
Friend.belongsTo(User, { foreignKey: 'requester_id', as: 'requester' }); // 친구 요청을 보낸 사용자
Friend.belongsTo(User, { foreignKey: 'receiver_id', as: 'receiver' }); // 친구 요청을 받은 사용자
User.hasMany(Friend, { foreignKey: 'requester_id', as: 'sentRequests' }); // 친구 요청을 보낸 목록
User.hasMany(Friend, { foreignKey: 'receiver_id', as: 'receivedRequests' }); // 친구 요청을 받은 목록
module.exports = Friend;
// models/Invite.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');
const User = require('./User');
const Meeting = require('./Meeting');
const Invite = sequelize.define('Invite', {
status: {
type: DataTypes.ENUM('PENDING', 'ACCEPTED', 'DECLINED'),
allowNull: false,
defaultValue: 'PENDING',
},
}, {
tableName: 'Invites',
timestamps: true,
underscored: true,
indexes: [
{
unique: true,
fields: ['meeting_id', 'invitee_id']
},
{
fields: ['status']
}
]
});
// 관계 설정
// Invite.belongsTo(Meeting, { foreignKey: 'meeting_id', as: 'meeting' });
// Invite.belongsTo(User, { foreignKey: 'inviter_id', as: 'inviter' }); // 초대한 사용자
// Invite.belongsTo(User, { foreignKey: 'invitee_id', as: 'invitee' }); // 초대받은 사용자
// User.hasMany(Invite, { foreignKey: 'inviter_id', as: 'sentInvites' }); // 보낸 초대 목록
// User.hasMany(Invite, { foreignKey: 'invitee_id', as: 'receivedInvites' }); // 받은 초대 목록
// Meeting.hasMany(Invite, { foreignKey: 'meeting_id', as: 'invites' }); // 해당 미팅의 모든 초대
module.exports = Invite;
\ No newline at end of file
// models/index.js
const sequelize = require('../config/sequelize');
const User = require('./User');
const User = require('./user');
const Friend = require('./Friend');
const Schedule = require('./Schedule');
const Meeting = require('./Meeting');
const MeetingParticipant = require('./MeetingParticipant'); //폴더명수정
const Friend = require('./Friend');
const FcmToken = require('./fcmToken');
const MeetingParticipant = require('./MeetingParticipant');
const ChatRooms = require('./ChatRooms');
// 관계 설정
Friend.belongsTo(User, { foreignKey: 'requester_id', as: 'requester' }); // 친구 요청을 보낸 사용자
Friend.belongsTo(User, { foreignKey: 'receiver_id', as: 'receiver' }); // 친구 요청을 받은 사용자
User.hasMany(Friend, { foreignKey: 'requester_id', as: 'sentRequests' }); // 친구 요청을 보낸 목록
User.hasMany(Friend, { foreignKey: 'receiver_id', as: 'receivedRequests' }); // 친구 요청을 받은 목록
// 연관 관계 설정
Meeting.belongsTo(User, { foreignKey: 'created_by', as: 'creator' });
User.hasMany(Meeting, { foreignKey: 'created_by', as: 'meetings' });
MeetingParticipant.belongsTo(Meeting, { foreignKey: 'meeting_id', as: 'meeting' });
Meeting.hasMany(MeetingParticipant, { foreignKey: 'meeting_id', as: 'participants' });
MeetingParticipant.belongsTo(User, { foreignKey: 'user_id', as: 'user' });
User.hasMany(MeetingParticipant, { foreignKey: 'user_id', as: 'meetingParticipations' });
Schedule.belongsTo(User, { foreignKey: 'user_id', as: 'user' });
User.hasMany(Schedule, { foreignKey: 'user_id', as: 'schedules' });
module.exports = {
sequelize,
User,
Friend,
Schedule,
Meeting,
MeetingParticipant,
ChatRooms,
sequelize,
User,
Schedule,
......
// models/Meeting.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');
const sequelize = require('../config/sequelize');
const User = require('./User');
const Meeting = sequelize.define('Meeting', {
title: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
},
start_time: {
type: DataTypes.DATE,
allowNull: false,
},
end_time: {
type: DataTypes.DATE,
allowNull: false,
},
location: {
type: DataTypes.STRING,
},
deadline: {
type: DataTypes.DATE,
},
type: {
type: DataTypes.ENUM('OPEN', 'CLOSE'),
allowNull: false,
},
created_by: {
type: DataTypes.INTEGER,
allowNull: false,
},
chatRoomId: { // 새로운 필드 추가
type: DataTypes.STRING,
allowNull: false,
},
title: {
type: DataTypes.STRING,
allowNull: false,
},
description: {
type: DataTypes.TEXT,
},
time_idx_start: {
type: DataTypes.INTEGER,
allowNull: false,
},
time_idx_end: {
type: DataTypes.INTEGER,
allowNull: false,
},
location: {
type: DataTypes.STRING,
},
time_idx_deadline: {
type: DataTypes.INTEGER,
},
type: {
type: DataTypes.ENUM('OPEN', 'CLOSE'),
allowNull: false,
defaultValue: 'OPEN',
},
chatRoomId: {
type: DataTypes.UUID,
allowNull: false,
},
max_num: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 10, // 기본값 설정 (필요에 따라 조정)
},
cur_num: {
type: DataTypes.INTEGER,
allowNull: false,
defaultValue: 1, // 생성자 자신 포함
},
}, {
tableName: 'Meetings',
timestamps: false,
tableName: 'Meetings',
timestamps: true,
underscored: true,
});
// 연관 관계 설정
Meeting.belongsTo(User, { foreignKey: 'created_by', as: 'creator' });
User.hasMany(Meeting, { foreignKey: 'created_by', as: 'meetings' });
module.exports = Meeting;
// models/MeetingParticipant.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');
const Meeting =require('./Meeting');
const User = require('./User');
const sequelize = require('../config/sequelize');
const MeetingParticipant = sequelize.define('MeetingParticipant', {
meeting_id: {
type: DataTypes.INTEGER,
allowNull: false
const MeetingParticipant = sequelize.define(
'MeetingParticipant',
{
id: {
type: DataTypes.INTEGER,
autoIncrement: true,
primaryKey: true,
},
meeting_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false,
},
},
user_id: {
type: DataTypes.INTEGER,
allowNull: false
{
tableName: 'MeetingParticipants', // 테이블 이름 설정
timestamps: false, // createdAt, updatedAt 필드 비활성화
}
}, {
tableName: 'MeetingParticipants',
timestamps: false,
});
MeetingParticipant.belongsTo(Meeting, { foreignKey: 'meeting_id', as: 'meeting' });
Meeting.hasMany(MeetingParticipant, { foreignKey: 'meeting_id', as: 'participants' });
MeetingParticipant.belongsTo(User, { foreignKey: 'user_id', as: 'user' });
User.hasMany(MeetingParticipant, { foreignKey: 'user_id', as: 'meetingParticipations' });
);
module.exports = MeetingParticipant;
// models/Schedule.js
const { DataTypes } = require('sequelize');
const sequelize = require('../config/sequelize');
const User = require('./User');
const User = require('./user');
const Schedule = sequelize.define('Schedule', {
title: {
type: DataTypes.STRING,
allowNull: false,
},
start_time: {
type: DataTypes.DATE,
allowNull: false,
},
end_time: {
type: DataTypes.DATE,
time_idx: { // 일주일을 15분 단위로 나눈 시간 인덱스
type: DataTypes.INTEGER,
allowNull: false,
validate: {
min: 0,
max: 671, // 7일 * 24시간 * 4 (15분 단위) - 1
},
},
is_fixed: {
type: DataTypes.BOOLEAN,
allowNull: false,
defaultValue: false
defaultValue: false,
},
expiry_date: {
type: DataTypes.DATE,
allowNull: true
}
}, {
tableName: 'Schedules',
timestamps: true, // created_at과 updated_at 자동 관리
timestamps: true, // createdAt과 updatedAt 자동 관리
indexes: [
{
unique: true,
fields: ['user_id', 'time_idx'],
name: 'unique_schedule_per_user_time',
},
{
fields: ['time_idx'],
},
],
});
Schedule.belongsTo(User, { foreignKey: 'user_id', as: 'user' });
User.hasMany(Schedule, { foreignKey: 'user_id', as: 'schedules' });
module.exports = Schedule;
\ No newline at end of file
module.exports = Schedule;
......@@ -5,11 +5,11 @@ const sequelize = require('../config/sequelize');
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING, // VARCHAR
type: DataTypes.STRING,
allowNull: false,
},
email: {
type: DataTypes.STRING, // VARCHAR
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment