Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • websystem1/webback
1 result
Select Git revision
Show changes
Commits on Source (16)
Showing
with 335 additions and 242 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 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,
Schedule,
Meeting,
MeetingParticipant,
Friend,
sequelize,
User,
Friend,
Schedule,
Meeting,
MeetingParticipant,
ChatRooms,
};
// 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: {
......