From 58234d3c30e01eed440cfb4b1e4ffc3bec0f96b8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=EC=A1=B0=EB=8C=80=ED=9D=AC?= <joedaehui@ajou.ac.kr>
Date: Thu, 14 Nov 2024 23:47:24 +0900
Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=BC=80=EC=A4=84=20?=
 =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=20=EC=A4=91=EB=B3=B5=20=EC=BD=94?=
 =?UTF-8?q?=EB=93=9C=20=ED=95=A8=EC=88=98=ED=99=94=20(#5)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/scheduleService.js | 143 ++++++++++++++++++------------------
 1 file changed, 71 insertions(+), 72 deletions(-)

diff --git a/services/scheduleService.js b/services/scheduleService.js
index 7fd1707..79a787f 100644
--- a/services/scheduleService.js
+++ b/services/scheduleService.js
@@ -3,6 +3,54 @@ const Schedule = require('../models/Schedule');
 
 class schedulService {
 
+    /**
+     * transactin wrapper 함수
+     */
+    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,
+                    expiry_date: {
+                        [Op.gt]: new Date()
+                    }
+                }
+            ]
+        };
+
+        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');
+        }
+    }
+
     /**
      * 유동 스케줄 만료일 구하기
      */
@@ -19,16 +67,9 @@ class schedulService {
      * 사용자 스케줄 생성
      */
     async createSchedule({ userId, title, start_time, end_time, is_fixed }) {
-        const transaction = await Schedule.sequelize.transaction();
+        return this.withTransaction(async (transaction) => {
+            this.validateScheduleTime(start_time, end_time);
 
-        try {
-
-            // 일정 시작 시간 - 종료 시간 유효성 검사
-            if (new Date(start_time) >= new Date(end_time)) {
-                throw new Error('Start time must be before end time');
-            }
-
-            // 중복 검사
             const overlap = await this.checkScheduleOverlap(userId, start_time, end_time);
             if (overlap) {
                 throw new Error('Schedule overlaps with existing schedule');
@@ -43,75 +84,57 @@ class schedulService {
                 expiry_date: is_fixed ? null : this.getNextMonday()
             };
 
-            const schedule = await Schedule.create(scheduleData, { transaction });
-            await transaction.commit();
-            return schedule;
-        } catch (error) {
-            await transaction.rollback();
-            throw new Error(`Failed to create schedule: ${error.message}`);
-        }
+            return Schedule.create(scheduleData, { transaction });
+        });
     }
 
     /**
      * 사용자 스케줄 수정
      */
     async updateSchedule(id, userId, updateData) {
-        const transaction = await Schedule.sequelize.transaction();
-
-        try {
+        return this.withTransaction(async (transaction) => {
             const schedule = await Schedule.findOne({
-                where: { id, user_id: userId }
+                where: { id, user_id: userId },
+                transaction
             });
 
             if (!schedule) {
                 throw new Error('Schedule not found');
             }
 
-            // 일정 시작 시간 - 종료 시간 유효성 검사
-            if (new Date(updateData.start_time) >= new Date(updateData.end_time)) {
-                throw new Error('Start time must be before end time');
-            }
+            this.validateScheduleTime(updateData.start_time, updateData.end_time);
 
-            // 중복 검사
-            const overlap = await this.checkScheduleOverlap(userId, updateData.start_time, updateData.end_time);
+            const overlap = await this.checkScheduleOverlap(
+                userId, 
+                updateData.start_time, 
+                updateData.end_time,
+                id
+            );
             if (overlap) {
                 throw new Error('Schedule overlaps with existing schedule');
             }
 
-            // 스케줄 타입 변경하지 못하도록 update값 삭제 -> 기존값 유지
             delete updateData.is_fixed;
-            
-            await schedule.update(updateData, { transaction });
-            await transaction.commit();
-            return schedule;
-        } catch (error) {
-            await transaction.rollback();
-            throw new Error(`Failed to update schedule: ${error.message}`);
-        }
+            return schedule.update(updateData, { transaction });
+        });
     }
  
     /**
      * 사용자 스케줄 삭제
      */
     async deleteSchedule(id, userId) {
-        const transaction = await Schedule.sequelize.transaction();
-
-        try {
-            const schedule = await Schedule.destroy({
+        return this.withTransaction(async (transaction) => {
+            const result = await Schedule.destroy({
                 where: { id, user_id: userId },
                 transaction
             });
 
-            if (!schedule) {
+            if (!result) {
                 throw new Error('Schedule not found');
             }
 
-            await transaction.commit();
             return true;
-        } catch (error) {
-            await transaction.rollback();
-            throw new Error(`Failed to delete schedule: ${error.message}`);
-        }
+        });
     }
     
     /**
@@ -119,22 +142,10 @@ class schedulService {
      */
     async getAllSchedules(userId) {
         try {
-            const schedules = await Schedule.findAll({
-                where: {
-                    user_id: userId,
-                    [Op.or]: [
-                        { is_fixed: true },
-                        {
-                            is_fixed: false,
-                            expiry_date: {
-                                [Op.gt]: new Date()
-                            }
-                        }
-                    ]
-                },
+            return Schedule.findAll({
+                where: this.getScheduleWhereClause(userId),
                 order: [['start_time', 'ASC']]
             });
-            return schedules;
         } catch (error) {
             throw new Error(`Failed to fetch schedules: ${error.message}`);
         }
@@ -146,19 +157,7 @@ class schedulService {
     async getScheduleById(id, userId) {
         try {
             const schedule = await Schedule.findOne({
-                where: {
-                    id,
-                    user_id: userId,
-                    [Op.or]: [
-                        { is_fixed: true },
-                        {
-                            is_fixed: false,
-                            expiry_date: {
-                                [Op.gt]: new Date()
-                            }
-                        }
-                    ]
-                }
+                where: this.getScheduleWhereClause(userId, id)
             });
             
             if (!schedule) {
-- 
GitLab