Newer
Older
const { Op } = require('sequelize');
const Schedule = require('../models/Schedule');
const ScheduleResponseDTO = require('../dtos/ScheduleResponseDTO');
*/
async withTransaction(callback) {
const transaction = await Schedule.sequelize.transaction();
try {
const result = await callback(transaction);
await transaction.commit();
return result;
} catch (error) {
await transaction.rollback();
throw error;
}
}
/**
* 공통 where 절 생성
*/
getScheduleWhereClause(userId, id = null) {
const where = {
user_id: userId,
[Op.or]: [
{ is_fixed: true },
{
is_fixed: false,
}
]
};
if (id) {
where.id = id;
}
return where;
}
/**
* 스케줄 유효성 검사
*/
validateScheduleTime(start_time, end_time) {
if (new Date(start_time) >= new Date(end_time)) {
throw new Error('Start time must be before end time');
}
}
getNextMonday(startTime) {
const date = new Date(startTime);
const nextMonday = new Date(date);
nextMonday.setDate(date.getDate() + daysUntilNextMonday);
nextMonday.setHours(0, 0, 0, 0); // 자정으로 설정
}
/**
* 사용자 스케줄 생성
*/
async createSchedule({ userId, title, start_time, end_time, is_fixed }) {
const schedule = await this.withTransaction(async (transaction) => {
const overlap = await this.checkScheduleOverlap(userId, start_time, end_time);
if (overlap) {
throw new Error('Schedule overlaps with existing schedule');
}
user_id: userId,
title,
start_time,
end_time,
is_fixed,
expiry_date: is_fixed ? null : this.getNextMonday(start_time)
return Schedule.create(scheduleData, { transaction });
});
/**
* 사용자 스케줄 수정
*/
async updateSchedule(id, userId, updateData) {
const updatedSchedule = await this.withTransaction(async (transaction) => {
this.validateScheduleTime(updateData.start_time, updateData.end_time);
if (overlap) {
throw new Error('Schedule overlaps with existing schedule');
}
...updateData,
expiry_date: is_fixed ? null : this.getNextMonday(updateData.start_time),
updatedAt: new Date()
};
return schedule.update(updatedDataWithExpiry, { transaction });
return new ScheduleResponseDTO(updatedSchedule);
/**
* 사용자 스케줄 삭제
*/
async deleteSchedule(id, userId) {
return this.withTransaction(async (transaction) => {
const result = await Schedule.destroy({
where: { id, user_id: userId },
transaction
// 삭제 성공 메시지 반환
return { message: 'Schedule successfully deleted' };
/**
* 해당 사용자의 스케줄 정보 조회
*/
async getAllSchedules(userId) {
try {
const schedulesDTO = schedules.map(schedule => new ScheduleResponseDTO(schedule));
return schedulesDTO;
} catch (error) {
throw new Error(`Failed to fetch schedules: ${error.message}`);
}
}
/**
* 해당 사용자의 특정 스케줄 조회
*/
async getScheduleById(id, userId) {
try {
const schedule = await Schedule.findOne({
if (!schedule) {
throw new Error('Schedule not found');
}
} catch (error) {
throw new Error(`Failed to fetch schedule: ${error.message}`);
}
}
*/
async cleanExpiredSchedules() {
try {
await Schedule.destroy({
where: {
is_fixed: false,
}
});
} catch (error) {
throw new Error(`Failed to clean expired schedules: ${error.message}`);
}
}
*/
async checkScheduleOverlap(userId, start_time, end_time, excludeId = null) {
try {
const where = {
user_id: userId,
[Op.or]: [
{
[Op.and]: [
{ start_time: { [Op.lte]: start_time } },
{ end_time: { [Op.gte]: start_time } }
]
},
{
[Op.and]: [
{ start_time: { [Op.gte]: start_time } },
{ start_time: { [Op.lte]: end_time } }
]
}
]
};
if (excludeId) {
where.id = { [Op.ne]: excludeId };
}
const overlappingSchedule = await Schedule.findOne({ where });
return overlappingSchedule;
} catch (error) {
throw new Error(`Failed to check schedule overlap: ${error.message}`);
}
}