From 8c6938023ae111cb2ede10d40f1e5bef9fdbeb93 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: Mon, 25 Nov 2024 20:15:36 +0900
Subject: [PATCH 01/14] =?UTF-8?q?refactor:=20=EB=AF=B8=ED=8C=85=20?=
 =?UTF-8?q?=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20=EC=A1=B0=ED=9A=8C=20?=
 =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=EC=97=90=20=EB=94=B0?=
 =?UTF-8?q?=EB=A5=B8=20dto=20=EC=88=98=EC=A0=95=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 dtos/MeetingDetailResponseDTO.js | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/dtos/MeetingDetailResponseDTO.js b/dtos/MeetingDetailResponseDTO.js
index 5d4ac75..c9a07ed 100644
--- a/dtos/MeetingDetailResponseDTO.js
+++ b/dtos/MeetingDetailResponseDTO.js
@@ -1,6 +1,6 @@
 // dtos/MeetingResponseDTO.js
 class MeetingDetailResponseDTO {
-  constructor(meeting) {
+  constructor(meeting, isScheduleConflict) {
       this.id = meeting.id;
       this.title = meeting.title;
       this.description = meeting.description;
@@ -10,6 +10,7 @@ class MeetingDetailResponseDTO {
       this.time_idx_deadline = meeting.time_idx_deadline;
       this.type = meeting.type;
       this.creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
+      this.isScheduleConflict = isScheduleConflict; 
       this.participants = meeting.participants.map(participant => ({
           userId: participant.user_id,
           name: participant.participantUser ? participant.participantUser.name : 'Unknown',
-- 
GitLab


From 3d4eadc9d4f72693ddfb5b40d9a9cfb24cffe657 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: Mon, 25 Nov 2024 20:15:53 +0900
Subject: [PATCH 02/14] =?UTF-8?q?refactor:=20=EB=AF=B8=ED=8C=85=20?=
 =?UTF-8?q?=EB=AA=A9=EB=A1=9D/=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20?=
 =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EC=88=98=EC=A0=95=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.js | 55 +++++++++++++++++++++++++-------------
 1 file changed, 37 insertions(+), 18 deletions(-)

diff --git a/services/meetingService.js b/services/meetingService.js
index d7b6023..653b73a 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -299,21 +299,34 @@ class MeetingService {
                 {
                     model: MeetingParticipant,
                     as: 'participants',
-                    where: { user_id: userId }, // userId�� 留ㅽ븨�� 誘명똿留� 媛��몄샂
-                    attributes: [], 
+                    required: false, 
+                    attributes: [],
                 },
                 {
                     model: User,
                     as: 'creator',
-                    attributes: ['name'], // 誘명똿 �앹꽦�먯쓽 �대쫫留� �꾩슂
-                },
-            ],
+                    attributes: ['name'],
+                }
+            ]
         });
-
-        return meetings.map((meeting) => {
+    
+        return Promise.all(meetings.map(async (meeting) => {
+            const isParticipant = await MeetingParticipant.findOne({
+                where: {
+                    meeting_id: meeting.id,
+                    user_id: userId
+                }
+            });
+    
+            const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
+                userId,
+                meeting.time_idx_start,
+                meeting.time_idx_end
+            );
+    
             const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
-            return new MeetingResponseDTO(meeting, true, false, creatorName);
-        });
+            return new MeetingResponseDTO(meeting, !!isParticipant, hasConflict, creatorName);
+        }));
     }
 
   
@@ -451,7 +464,7 @@ class MeetingService {
     
 
     
-    async getMeetingDetail(meetingId) {
+    async getMeetingDetail(meetingId, userId) {
         const meeting = await Meeting.findByPk(meetingId, {
             include: [
                 {
@@ -465,19 +478,25 @@ class MeetingService {
                     include: [
                         {
                             model: User,
-                            as: "user", // 'participantUser'�먯꽌 'user'濡� �섏젙
+                            as: "user",
                             attributes: ["name", "email"],
-                        },
-                    ],
-                },
-            ],
+                        }
+                    ]
+                }
+            ]
         });
-
+    
         if (!meeting) {
             throw new Error("紐⑥엫�� 李얠쓣 �� �놁뒿�덈떎.");
         }
-
-        return new MeetingDetailResponseDTO(meeting);
+    
+        const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
+            userId,
+            meeting.time_idx_start,
+            meeting.time_idx_end
+        );
+    
+        return new MeetingDetailResponseDTO(meeting, hasConflict);
     }
 
     /**
-- 
GitLab


From 00225eaabde4bc6af61bd343c5e73f22a03e5695 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: Mon, 25 Nov 2024 20:16:20 +0900
Subject: [PATCH 03/14] =?UTF-8?q?test,=20refactor:=20=EB=AF=B8=ED=8C=85=20?=
 =?UTF-8?q?=EB=AA=A9=EB=A1=9D/=EC=83=81=EC=84=B8=20=EC=A0=95=EB=B3=B4=20?=
 =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94?=
 =?UTF-8?q?=EB=93=9C=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.test.js | 914 ++++++++++++++++----------------
 1 file changed, 449 insertions(+), 465 deletions(-)

diff --git a/services/meetingService.test.js b/services/meetingService.test.js
index 1dc2f05..8615ca5 100644
--- a/services/meetingService.test.js
+++ b/services/meetingService.test.js
@@ -1,10 +1,10 @@
 // test/meetingService.test.js
-const sequelize = require('../config/sequelize'); 
+const sequelize = require('../config/sequelize');
 const { Op } = require('sequelize');
 const { Meeting, MeetingParticipant, User, Schedule } = require('../models');
 const MeetingService = require('../services/meetingService');
 const ScheduleService = require('../services/scheduleService');
-const ChatRooms = require('../models/ChatRooms'); 
+const ChatRooms = require('../models/ChatRooms');
 const CreateMeetingRequestDTO = require('../dtos/CreateMeetingRequestDTO');
 const MeetingResponseDTO = require('../dtos/MeetingResponseDTO');
 const MeetingDetailResponseDTO = require('../dtos/MeetingDetailResponseDTO');
@@ -12,486 +12,470 @@ const MeetingDetailResponseDTO = require('../dtos/MeetingDetailResponseDTO');
 
 
 beforeAll(async () => {
-  // �곗씠�곕쿋�댁뒪 珥덇린�� 諛� �숆린��
-  await sequelize.sync({ force: true });
+    // �곗씠�곕쿋�댁뒪 珥덇린�� 諛� �숆린��
+    await sequelize.sync({ force: true });
 });
 
 beforeEach(async () => {
-  // �몃옒 �� �쒖꽌�� �곕씪 �곗씠�� ��젣
-  await MeetingParticipant.destroy({ where: {}, truncate: true });
-  await Meeting.destroy({ where: {}, truncate: true });
-  await Schedule.destroy({ where: {}, truncate: true });
-  await User.destroy({ where: {}, truncate: true });
-
-  // �붾� �ъ슜�� �곗씠�� �쎌엯
-  await User.bulkCreate([
-      { id: 1, name: 'Alice', email: 'alice@example.com' },
-      { id: 2, name: 'Bob', email: 'bob@example.com' },
-      { id: 3, name: 'Charlie', email: 'charlie@example.com' },
-  ]);
-
-  // ChatRooms Mock �ㅼ젙
-  jest.spyOn(ChatRooms.prototype, 'save').mockResolvedValue(undefined);
-  jest.spyOn(ChatRooms, 'findOne').mockResolvedValue({
-      participants: [],
-      isOnline: new Map(),
-      lastReadAt: new Map(),
-      lastReadLogId: new Map(),
-      save: jest.fn().mockResolvedValue(true),
-  });
+    // �몃옒 �� �쒖꽌�� �곕씪 �곗씠�� ��젣
+    await MeetingParticipant.destroy({ where: {}, truncate: true });
+    await Meeting.destroy({ where: {}, truncate: true });
+    await Schedule.destroy({ where: {}, truncate: true });
+    await User.destroy({ where: {}, truncate: true });
+
+    // �붾� �ъ슜�� �곗씠�� �쎌엯
+    await User.bulkCreate([
+        { id: 1, name: 'Alice', email: 'alice@example.com' },
+        { id: 2, name: 'Bob', email: 'bob@example.com' },
+        { id: 3, name: 'Charlie', email: 'charlie@example.com' },
+    ]);
+
+    // ChatRooms Mock �ㅼ젙
+    jest.spyOn(ChatRooms.prototype, 'save').mockResolvedValue(undefined);
+    jest.spyOn(ChatRooms, 'findOne').mockResolvedValue({
+        participants: [],
+        isOnline: new Map(),
+        lastReadAt: new Map(),
+        lastReadLogId: new Map(),
+        save: jest.fn().mockResolvedValue(true),
+    });
 });
 
 afterEach(() => {
-  // Mock 蹂듭썝 諛� 珥덇린��
-  jest.restoreAllMocks();
-  jest.clearAllMocks();
+    // Mock 蹂듭썝 諛� 珥덇린��
+    jest.restoreAllMocks();
+    jest.clearAllMocks();
 });
 
 afterAll(async () => {
-  // �곗씠�곕쿋�댁뒪 �곌껐 醫낅즺
-  await sequelize.close();
+    // �곗씠�곕쿋�댁뒪 �곌껐 醫낅즺
+    await sequelize.close();
 });
 
-describe('MeetingService - getMeetings', () => {
-  beforeEach(async () => {
-      await MeetingParticipant.destroy({ where: {} });
-      await Meeting.destroy({ where: {} });
-      await Schedule.destroy({ where: {} });
-      await User.destroy({ where: {} });
-
-      // Create dummy users
-      await User.bulkCreate([
-          { id: 1, name: 'Alice', email: 'alice@example.com' },
-          { id: 2, name: 'Bob', email: 'bob@example.com' },
-          { id: 3, name: 'Charlie', email: 'charlie@example.com' },
-      ]);
-  });
-
-  test('should retrieve meetings where the user is a participant', async () => {
-      const meetingData = {
-          title: 'Meeting with Alice',
-          description: 'Discuss project.',
-          time_idx_start: 10,
-          time_idx_end: 20,
-          location: 'Room A',
-          time_idx_deadline: 8,
-          type: 'OPEN',
-          created_by: 1,
-      };
-
-      const createdMeeting = await MeetingService.createMeeting(meetingData);
-
-      await MeetingParticipant.create({
-          meeting_id: createdMeeting.meeting_id,
-          user_id: 2,
-      });
-
-      const meetings = await MeetingService.getMeetings(2); // Bob's user ID
-
-      expect(meetings).toBeDefined();
-      expect(Array.isArray(meetings)).toBe(true);
-      expect(meetings.length).toBe(1);
-
-      const [meeting] = meetings;
-      expect(meeting.title).toBe('Meeting with Alice');
-      expect(meeting.creatorName).toBe('Alice');
-      expect(meeting.isParticipant).toBe(true);
-  });
-
-  test('should retrieve meetings where the user is the creator', async () => {
-      const meetingData = {
-          title: 'Alice-created Meeting',
-          description: 'Team discussion.',
-          time_idx_start: 15,
-          time_idx_end: 25,
-          location: 'Room B',
-          time_idx_deadline: 12,
-          type: 'OPEN',
-          created_by: 1,
-      };
-
-      await MeetingService.createMeeting(meetingData);
-
-      const meetings = await MeetingService.getMeetings(1); // Alice's user ID
-
-      expect(meetings).toBeDefined();
-      expect(Array.isArray(meetings)).toBe(true);
-      expect(meetings.length).toBe(1);
-
-      const [meeting] = meetings;
-      expect(meeting.title).toBe('Alice-created Meeting');
-      expect(meeting.creatorName).toBe('Alice');
-      expect(meeting.isParticipant).toBe(true);
-  });
-
-  test('should not include meetings where the user is neither a participant nor the creator', async () => {
-      const meetingData = {
-          title: 'Meeting with Bob',
-          description: 'General discussion.',
-          time_idx_start: 30,
-          time_idx_end: 40,
-          location: 'Room C',
-          time_idx_deadline: 28,
-          type: 'OPEN',
-          created_by: 2,
-      };
-
-      await MeetingService.createMeeting(meetingData);
-
-      const meetings = await MeetingService.getMeetings(1); // Alice's user ID
-
-      expect(meetings).toBeDefined();
-      expect(Array.isArray(meetings)).toBe(true);
-      expect(meetings.length).toBe(0); // Alice is not a participant or the creator
-  });
-
-  test('should retrieve multiple meetings correctly', async () => {
-      const meetingData1 = {
-          title: 'Meeting 1',
-          description: 'First meeting.',
-          time_idx_start: 50,
-          time_idx_end: 60,
-          location: 'Room D',
-          time_idx_deadline: 48,
-          type: 'OPEN',
-          created_by: 1,
-      };
-
-      const meetingData2 = {
-          title: 'Meeting 2',
-          description: 'Second meeting.',
-          time_idx_start: 70,
-          time_idx_end: 80,
-          location: 'Room E',
-          time_idx_deadline: 68,
-          type: 'OPEN',
-          created_by: 2,
-      };
-
-      await MeetingService.createMeeting(meetingData1);
-      const meeting2 = await MeetingService.createMeeting(meetingData2);
-
-    
-      await MeetingParticipant.create({
-          meeting_id: meeting2.meeting_id,
-          user_id: 1,
-      });
-
-      const meetings = await MeetingService.getMeetings(1); // Alice's user ID
-
-      expect(meetings).toBeDefined();
-      expect(Array.isArray(meetings)).toBe(true);
-      expect(meetings.length).toBe(2); // Alice is either the creator or a participant in two meetings
-
-      const meetingTitles = meetings.map((m) => m.title);
-      expect(meetingTitles).toContain('Meeting 1');
-      expect(meetingTitles).toContain('Meeting 2');
-  });
-
-  test('should return an empty array if the user has no meetings', async () => {
-      const meetings = await MeetingService.getMeetings(3); 
-      expect(meetings).toBeDefined();
-      expect(Array.isArray(meetings)).toBe(true);
-      expect(meetings.length).toBe(0); 
-  });
+describe('MeetingService - �꾩껜 誘명똿 議고쉶 �뚯뒪��', () => {
+    beforeEach(async () => {
+        await MeetingParticipant.destroy({ where: {} });
+        await Meeting.destroy({ where: {} });
+        await Schedule.destroy({ where: {} });
+        await User.destroy({ where: {} });
+
+        // �붾� �ъ슜�� �앹꽦
+        await User.bulkCreate([
+            { id: 1, name: 'Alice', email: 'alice@example.com' },
+            { id: 2, name: 'Bob', email: 'bob@example.com' },
+            { id: 3, name: 'Charlie', email: 'charlie@example.com' }
+        ]);
+
+        // �ㅼ�以� 異⑸룎 泥댄겕 Mock �ㅼ젙
+        jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime')
+            .mockImplementation(async (userId, start, end) => {
+                // 36-38 �쒓컙�� 異⑸룎
+                if (start <= 38 && end >= 36) return true;
+                // 51 �쒓컙�� 異⑸룎 (Bob�� 媛쒖씤 �쇱젙)
+                if (userId === 2 && start <= 51 && end >= 51) return true;
+                return false;
+            });
+    });
+
+    test('紐⑤뱺 誘명똿 紐⑸줉 議고쉶 諛� �ㅼ�以� 異⑸룎 �뺤씤', async () => {
+        // 1. Alice�� �ㅼ�以� �깅줉
+        await ScheduleService.createSchedules({
+            userId: 1,
+            title: '湲곗〈 �쇱젙',
+            is_fixed: true,
+            events: [
+                { time_idx: 36 },
+                { time_idx: 37 },
+                { time_idx: 38 }
+            ]
+        });
+
+        // 2. getCurrentTimeIdx Mock �ㅼ젙
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx')
+            .mockReturnValue(30);
+
+        const meetingData1 = {
+            title: '�꾩묠 誘명똿',
+            time_idx_start: 36,
+            time_idx_end: 38,
+            created_by: 2,
+            type: 'OPEN',
+            time_idx_deadline: 35,
+            location: 'Room A'
+        };
+
+        const meetingData2 = {
+            title: '�먯떖 誘명똿',
+            time_idx_start: 44,
+            time_idx_end: 46,
+            created_by: 3,
+            type: 'OPEN',
+            time_idx_deadline: 43,
+            location: 'Room B'
+        };
+
+        await MeetingService.createMeeting(meetingData1);
+        await MeetingService.createMeeting(meetingData2);
+
+        const meetings = await MeetingService.getMeetings(1);
+
+        expect(meetings.length).toBe(2);
+
+        const morningMeeting = meetings.find(m => m.title === '�꾩묠 誘명똿');
+        expect(morningMeeting.isScheduleConflict).toBe(true);
+        expect(morningMeeting.creatorName).toBe('Bob');
+        expect(morningMeeting.isParticipant).toBe(false);
+
+        const lunchMeeting = meetings.find(m => m.title === '�먯떖 誘명똿');
+        expect(lunchMeeting.isScheduleConflict).toBe(false);
+        expect(lunchMeeting.creatorName).toBe('Charlie');
+        expect(lunchMeeting.isParticipant).toBe(false);
+    });
+
+    test('誘명똿 �곸꽭 �뺣낫 議고쉶 諛� 異⑸룎 �뺤씤', async () => {
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx')
+            .mockReturnValue(35);
+
+        jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime')
+            .mockImplementation(async (userId, start, end) => {
+                return start === 40 && end === 42 && userId === 1;
+            });
+
+        const meeting = await MeetingService.createMeeting({
+            title: '�� 誘명똿',
+            time_idx_start: 40,
+            time_idx_end: 42,
+            created_by: 2,
+            type: 'OPEN',
+            time_idx_deadline: 39,
+            location: 'Room A'
+        });
+
+        await MeetingService.joinMeeting(meeting.meeting_id, 3);
+
+        const meetingDetail = await MeetingService.getMeetingDetail(meeting.meeting_id, 1);
+
+        expect(meetingDetail.title).toBe('�� 誘명똿');
+        expect(meetingDetail.isScheduleConflict).toBe(true);
+        expect(meetingDetail.creatorName).toBe('Bob');
+    });
+
+    test('�щ윭 �ъ슜�� 愿��먯뿉�쒖쓽 誘명똿 議고쉶', async () => {
+        const meeting = await MeetingService.createMeeting({
+            title: '怨듯넻 誘명똿',
+            time_idx_start: 50,
+            time_idx_end: 52,
+            created_by: 1,
+            type: 'OPEN',
+            location: 'Room A',
+            time_idx_deadline: 49
+        });
+
+        await ScheduleService.createSchedules({
+            userId: 2,
+            title: '媛쒖씤 �쇱젙',
+            is_fixed: true,
+            events: [{ time_idx: 51 }]
+        });
+
+        const aliceMeetings = await MeetingService.getMeetings(1);
+        const bobMeetings = await MeetingService.getMeetings(2);
+        const charlieMeetings = await MeetingService.getMeetings(3);
+
+        expect(aliceMeetings[0].isScheduleConflict).toBe(false);
+        expect(bobMeetings[0].isScheduleConflict).toBe(true);
+        expect(charlieMeetings[0].isScheduleConflict).toBe(false);
+
+        expect(aliceMeetings[0].isParticipant).toBe(true);
+        expect(bobMeetings[0].isParticipant).toBe(false);
+        expect(charlieMeetings[0].isParticipant).toBe(false);
+    });
 });
 
-
 describe('MeetingService - Integration: createMeeting, joinMeeting, getMeetings', () => {
-  beforeEach(async () => {
-      await MeetingParticipant.destroy({ where: {} });
-      await Meeting.destroy({ where: {} });
-      await Schedule.destroy({ where: {} });
-      await User.destroy({ where: {} });
-
-      // Create dummy users
-      await User.bulkCreate([
-          { id: 1, name: 'Alice', email: 'alice@example.com' },
-          { id: 2, name: 'Bob', email: 'bob@example.com' },
-          { id: 3, name: 'Charlie', email: 'charlie@example.com' },
-      ]);
-  });
-
-  test('should create a meeting, allow multiple users to join, and retrieve them correctly', async () => {
-      // Step 1: Create a meeting
-      const meetingData = {
-          title: 'Integration Test Meeting',
-          description: 'Test meeting for integration.',
-          time_idx_start: 10,
-          time_idx_end: 20,
-          location: 'Conference Room A',
-          time_idx_deadline: 8,
-          type: 'OPEN',
-          created_by: 1, 
-      };
-
-      const createdMeeting = await MeetingService.createMeeting(meetingData);
-
-      expect(createdMeeting).toBeDefined();
-      expect(createdMeeting.meeting_id).toBeDefined();
-      expect(createdMeeting.chatRoomId).toBeDefined();
-
-      // Step 2: Bob and Charlie join the meeting
-      jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5); // Ensure deadline is not passed
-      await MeetingService.joinMeeting(createdMeeting.meeting_id, 2); // Bob joins
-      await MeetingService.joinMeeting(createdMeeting.meeting_id, 3); // Charlie joins
-
-      // Step 3: Retrieve meetings for Alice (creator)
-      const aliceMeetings = await MeetingService.getMeetings(1);
-      expect(aliceMeetings).toBeDefined();
-      expect(aliceMeetings.length).toBe(1);
-
-      const aliceMeeting = aliceMeetings[0];
-      expect(aliceMeeting.title).toBe('Integration Test Meeting');
-      expect(aliceMeeting.creatorName).toBe('Alice');
-      expect(aliceMeeting.isParticipant).toBe(true);
-
-      // Step 4: Retrieve meetings for Bob (participant)
-      const bobMeetings = await MeetingService.getMeetings(2);
-      expect(bobMeetings).toBeDefined();
-      expect(bobMeetings.length).toBe(1);
-
-      const bobMeeting = bobMeetings[0];
-      expect(bobMeeting.title).toBe('Integration Test Meeting');
-      expect(bobMeeting.creatorName).toBe('Alice');
-      expect(bobMeeting.isParticipant).toBe(true);
-
-      // Step 5: Retrieve meetings for Charlie (participant)
-      const charlieMeetings = await MeetingService.getMeetings(3);
-      expect(charlieMeetings).toBeDefined();
-      expect(charlieMeetings.length).toBe(1);
-
-      const charlieMeeting = charlieMeetings[0];
-      expect(charlieMeeting.title).toBe('Integration Test Meeting');
-      expect(charlieMeeting.creatorName).toBe('Alice');
-      expect(charlieMeeting.isParticipant).toBe(true);
-  });
-
-  test('should not allow joining a meeting after the deadline', async () => {
-      const meetingData = {
-          title: 'Deadline Test Meeting',
-          description: 'Meeting to test deadlines.',
-          time_idx_start: 30,
-          time_idx_end: 40,
-          location: 'Conference Room B',
-          time_idx_deadline: 25,
-          type: 'OPEN',
-          created_by: 1, // Alice creates the meeting
-      };
-
-      const createdMeeting = await MeetingService.createMeeting(meetingData);
-
-      jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(26); // Simulate time after the deadline
-
-      await expect(
-          MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
-      ).rejects.toThrow('李멸� �좎껌�� 留덇컧�섏뿀�듬땲��.');
-  });
-
-  test('should prevent duplicate joining of a meeting', async () => {
-      const meetingData = {
-          title: 'Duplicate Join Test Meeting',
-          description: 'Meeting to test duplicate join handling.',
-          time_idx_start: 50,
-          time_idx_end: 60,
-          location: 'Conference Room C',
-          time_idx_deadline: 48,
-          type: 'OPEN',
-          created_by: 1, // Alice creates the meeting
-      };
-
-      const createdMeeting = await MeetingService.createMeeting(meetingData);
-
-      jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(45); // Ensure deadline is not passed
-      await MeetingService.joinMeeting(createdMeeting.meeting_id, 2); // Bob joins
-
-      // Attempt duplicate join
-      await expect(
-          MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
-      ).rejects.toThrow('�대� 李멸��� �ъ슜�먯엯�덈떎.');
-  });
-
-  test('should prevent joining when schedule conflicts', async () => {
-    const meetingData = {
-        title: 'Conflict Test Meeting',
-        description: 'Meeting to test schedule conflict.',
-        time_idx_start: 70,
-        time_idx_end: 80,
-        location: 'Conference Room D',
-        time_idx_deadline: 68,
-        type: 'OPEN',
-        created_by: 1, // Alice creates the meeting
-    };
-
-    const createdMeeting = await MeetingService.createMeeting(meetingData);
-
-    // Step 1: Virtually set current time before the deadline
-    jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(65); // �꾩옱 �쒓컙�� �곕뱶�쇱씤蹂대떎 �묒쓬
-
-    // Step 2: Simulate schedule conflict
-    jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime').mockResolvedValue(true); // �ㅼ�以� 異⑸룎 諛쒖깮
-
-    // Step 3: Expect schedule conflict error
-    await expect(
-        MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
-    ).rejects.toThrow('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ 紐⑥엫�� 李멸��섏꽭��.');
-});
+    beforeEach(async () => {
+        await MeetingParticipant.destroy({ where: {} });
+        await Meeting.destroy({ where: {} });
+        await Schedule.destroy({ where: {} });
+        await User.destroy({ where: {} });
+
+        // Create dummy users
+        await User.bulkCreate([
+            { id: 1, name: 'Alice', email: 'alice@example.com' },
+            { id: 2, name: 'Bob', email: 'bob@example.com' },
+            { id: 3, name: 'Charlie', email: 'charlie@example.com' },
+        ]);
+    });
+
+    test('should create a meeting, allow multiple users to join, and retrieve them correctly', async () => {
+        // Step 1: Create a meeting
+        const meetingData = {
+            title: 'Integration Test Meeting',
+            description: 'Test meeting for integration.',
+            time_idx_start: 10,
+            time_idx_end: 20,
+            location: 'Conference Room A',
+            time_idx_deadline: 8,
+            type: 'OPEN',
+            created_by: 1,
+        };
+
+        const createdMeeting = await MeetingService.createMeeting(meetingData);
+
+        expect(createdMeeting).toBeDefined();
+        expect(createdMeeting.meeting_id).toBeDefined();
+        expect(createdMeeting.chatRoomId).toBeDefined();
+
+        // Step 2: Bob and Charlie join the meeting
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5); // Ensure deadline is not passed
+        await MeetingService.joinMeeting(createdMeeting.meeting_id, 2); // Bob joins
+        await MeetingService.joinMeeting(createdMeeting.meeting_id, 3); // Charlie joins
+
+        // Step 3: Retrieve meetings for Alice (creator)
+        const aliceMeetings = await MeetingService.getMeetings(1);
+        expect(aliceMeetings).toBeDefined();
+        expect(aliceMeetings.length).toBe(1);
+
+        const aliceMeeting = aliceMeetings[0];
+        expect(aliceMeeting.title).toBe('Integration Test Meeting');
+        expect(aliceMeeting.creatorName).toBe('Alice');
+        expect(aliceMeeting.isParticipant).toBe(true);
+
+        // Step 4: Retrieve meetings for Bob (participant)
+        const bobMeetings = await MeetingService.getMeetings(2);
+        expect(bobMeetings).toBeDefined();
+        expect(bobMeetings.length).toBe(1);
+
+        const bobMeeting = bobMeetings[0];
+        expect(bobMeeting.title).toBe('Integration Test Meeting');
+        expect(bobMeeting.creatorName).toBe('Alice');
+        expect(bobMeeting.isParticipant).toBe(true);
+
+        // Step 5: Retrieve meetings for Charlie (participant)
+        const charlieMeetings = await MeetingService.getMeetings(3);
+        expect(charlieMeetings).toBeDefined();
+        expect(charlieMeetings.length).toBe(1);
+
+        const charlieMeeting = charlieMeetings[0];
+        expect(charlieMeeting.title).toBe('Integration Test Meeting');
+        expect(charlieMeeting.creatorName).toBe('Alice');
+        expect(charlieMeeting.isParticipant).toBe(true);
+    });
+
+    test('should not allow joining a meeting after the deadline', async () => {
+        const meetingData = {
+            title: 'Deadline Test Meeting',
+            description: 'Meeting to test deadlines.',
+            time_idx_start: 30,
+            time_idx_end: 40,
+            location: 'Conference Room B',
+            time_idx_deadline: 25,
+            type: 'OPEN',
+            created_by: 1, // Alice creates the meeting
+        };
+
+        const createdMeeting = await MeetingService.createMeeting(meetingData);
+
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(26); // Simulate time after the deadline
+
+        await expect(
+            MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
+        ).rejects.toThrow('李멸� �좎껌�� 留덇컧�섏뿀�듬땲��.');
+    });
+
+    test('should prevent duplicate joining of a meeting', async () => {
+        const meetingData = {
+            title: 'Duplicate Join Test Meeting',
+            description: 'Meeting to test duplicate join handling.',
+            time_idx_start: 50,
+            time_idx_end: 60,
+            location: 'Conference Room C',
+            time_idx_deadline: 48,
+            type: 'OPEN',
+            created_by: 1, // Alice creates the meeting
+        };
+
+        const createdMeeting = await MeetingService.createMeeting(meetingData);
+
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(45); // Ensure deadline is not passed
+        await MeetingService.joinMeeting(createdMeeting.meeting_id, 2); // Bob joins
+
+        // Attempt duplicate join
+        await expect(
+            MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
+        ).rejects.toThrow('�대� 李멸��� �ъ슜�먯엯�덈떎.');
+    });
+
+    test('should prevent joining when schedule conflicts', async () => {
+        const meetingData = {
+            title: 'Conflict Test Meeting',
+            description: 'Meeting to test schedule conflict.',
+            time_idx_start: 70,
+            time_idx_end: 80,
+            location: 'Conference Room D',
+            time_idx_deadline: 68,
+            type: 'OPEN',
+            created_by: 1, // Alice creates the meeting
+        };
+
+        const createdMeeting = await MeetingService.createMeeting(meetingData);
+
+        // Step 1: Virtually set current time before the deadline
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(65); // �꾩옱 �쒓컙�� �곕뱶�쇱씤蹂대떎 �묒쓬
+
+        // Step 2: Simulate schedule conflict
+        jest.spyOn(ScheduleService, 'checkScheduleOverlapByTime').mockResolvedValue(true); // �ㅼ�以� 異⑸룎 諛쒖깮
+
+        // Step 3: Expect schedule conflict error
+        await expect(
+            MeetingService.joinMeeting(createdMeeting.meeting_id, 2)
+        ).rejects.toThrow('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ 紐⑥엫�� 李멸��섏꽭��.');
+    });
 
 });
 
 describe('MeetingService2', () => {
-  beforeEach(async () => {
-      // �곗씠�곕쿋�댁뒪 珥덇린��
-      await MeetingParticipant.destroy({ where: {} });
-      await Meeting.destroy({ where: {} });
-      await Schedule.destroy({ where: {} });
-      await User.destroy({ where: {} });
-
-      // �붾� �ъ슜�� �앹꽦
-      await User.bulkCreate([
-          { id: 1, name: 'Alice', email: 'alice@example.com' },
-          { id: 2, name: 'Bob', email: 'bob@example.com' },
-          { id: 3, name: 'Charlie', email: 'charlie@example.com' },
-      ]);
-  });
-
-  test('�ъ슜�먭� �щ윭 紐⑥엫�� 李몄뿬�섍퀬 �대� �뺥솗�� 議고쉶�� �� �덉뼱�� �쒕떎', async () => {
-      // 1�④퀎: 寃뱀튂吏� �딅뒗 �쒓컙���� 紐⑥엫 �앹꽦
-      const meetingData1 = {
-          title: 'Morning Meeting',
-          description: 'Morning planning meeting.',
-          time_idx_start: 10,
-          time_idx_end: 20,
-          location: 'Room A',
-          time_idx_deadline: 8,
-          type: 'OPEN',
-          created_by: 1, // Alice媛� 紐⑥엫 �앹꽦
-      };
-
-      const meetingData2 = {
-          title: 'Lunch Meeting',
-          description: 'Lunch and discussion.',
-          time_idx_start: 30,
-          time_idx_end: 40,
-          location: 'Room B',
-          time_idx_deadline: 28,
-          type: 'OPEN',
-          created_by: 2, // Bob�� 紐⑥엫 �앹꽦
-      };
-
-      const meeting1 = await MeetingService.createMeeting(meetingData1);
-      const meeting2 = await MeetingService.createMeeting(meetingData2);
-
-      // 紐⑥엫 �앹꽦 �뺤씤
-      expect(meeting1).toBeDefined();
-      expect(meeting2).toBeDefined();
-
-      // 2�④퀎: Charlie媛� �� 紐⑥엫�� 李몄뿬
-      jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5); // 留덇컧 �쒓컙�� 珥덇낵�섏� �딅룄濡� �ㅼ젙
-      await MeetingService.joinMeeting(meeting1.meeting_id, 3); // Charlie媛� Morning Meeting 李몄뿬
-      await MeetingService.joinMeeting(meeting2.meeting_id, 3); // Charlie媛� Lunch Meeting 李몄뿬
-
-      // 3�④퀎: Charlie�� 李몄뿬 紐⑥엫 議고쉶
-      const charlieMeetings = await MeetingService.getMeetings(3); // Charlie�� �ъ슜�� ID
-      expect(charlieMeetings).toBeDefined();
-      expect(Array.isArray(charlieMeetings)).toBe(true);
-      expect(charlieMeetings.length).toBe(2); // Charlie�� 2媛쒖쓽 紐⑥엫�� 李몄뿬
-
-      // 媛� 紐⑥엫�� �몃� �뺣낫 �뺤씤
-      const morningMeeting = charlieMeetings.find(meeting => meeting.title === 'Morning Meeting');
-      const lunchMeeting = charlieMeetings.find(meeting => meeting.title === 'Lunch Meeting');
-
-      expect(morningMeeting).toBeDefined();
-      expect(morningMeeting.creatorName).toBe('Alice');
-      expect(morningMeeting.isParticipant).toBe(true);
-
-      expect(lunchMeeting).toBeDefined();
-      expect(lunchMeeting.creatorName).toBe('Bob');
-      expect(lunchMeeting.isParticipant).toBe(true);
-
-      // 異붽� 寃�利�: 媛� 紐⑥엫�� ���� Charlie�� �ㅼ�以꾩씠 �щ컮瑜닿쾶 �앹꽦�섏뿀�붿� �뺤씤
-      const charlieSchedules = await Schedule.findAll({ where: { user_id: 3 } });
-      expect(charlieSchedules.length).toBe(2 * (20 - 10 + 1)); // �� 紐⑥엫, 媛� 紐⑥엫留덈떎 11媛쒖쓽 �ㅼ�以� (10~20, 30~40)
-      
-      // 以묐났 �ㅼ�以꾩씠 �녿뒗吏� �뺤씤
-      const timeIndicesMorning = charlieSchedules
-          .filter(schedule => schedule.title === `踰덇컻 紐⑥엫: ${meetingData1.title}`)
-          .map(schedule => schedule.time_idx);
-      const timeIndicesLunch = charlieSchedules
-          .filter(schedule => schedule.title === `踰덇컻 紐⑥엫: ${meetingData2.title}`)
-          .map(schedule => schedule.time_idx);
-
-      // Morning Meeting�� �쒓컙�� �뺤씤
-      for (let i = 10; i <= 20; i++) {
-          expect(timeIndicesMorning).toContain(i);
-      }
-
-      // Lunch Meeting�� �쒓컙�� �뺤씤
-      for (let i = 30; i <= 40; i++) {
-          expect(timeIndicesLunch).toContain(i);
-      }
-  });
-
-  test('媛� �ъ슜�먯쓽 紐⑥엫�� �뺥솗�� 議고쉶�댁빞 �쒕떎', async () => {
-      // 1�④퀎: 寃뱀튂吏� �딅뒗 �쒓컙���� 紐⑥엫 �앹꽦
-      const meetingData1 = {
-          title: 'Morning Meeting',
-          description: 'Morning planning meeting.',
-          time_idx_start: 10,
-          time_idx_end: 20,
-          location: 'Room A',
-          time_idx_deadline: 8,
-          type: 'OPEN',
-          created_by: 1, // Alice媛� 紐⑥엫 �앹꽦
-      };
-
-      const meetingData2 = {
-          title: 'Lunch Meeting',
-          description: 'Lunch and discussion.',
-          time_idx_start: 30,
-          time_idx_end: 40,
-          location: 'Room B',
-          time_idx_deadline: 28,
-          type: 'OPEN',
-          created_by: 2, // Bob�� 紐⑥엫 �앹꽦
-      };
-
-      const meeting1 = await MeetingService.createMeeting(meetingData1);
-      const meeting2 = await MeetingService.createMeeting(meetingData2);
-
-      // 2�④퀎: Charlie媛� �� 紐⑥엫�� 李몄뿬
-      jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5); // 留덇컧 �쒓컙�� 珥덇낵�섏� �딅룄濡� �ㅼ젙
-      await MeetingService.joinMeeting(meeting1.meeting_id, 3); // Charlie媛� Morning Meeting 李몄뿬
-      await MeetingService.joinMeeting(meeting2.meeting_id, 3); // Charlie媛� Lunch Meeting 李몄뿬
-
-      // 3�④퀎: Alice�� 紐⑥엫 議고쉶
-      const aliceMeetings = await MeetingService.getMeetings(1); // Alice�� �ъ슜�� ID
-      expect(aliceMeetings.length).toBe(1); // Alice�� �섎굹�� 紐⑥엫 �앹꽦
-      expect(aliceMeetings[0].title).toBe('Morning Meeting');
-      expect(aliceMeetings[0].isParticipant).toBe(true);
-
-      // 4�④퀎: Bob�� 紐⑥엫 議고쉶
-      const bobMeetings = await MeetingService.getMeetings(2); // Bob�� �ъ슜�� ID
-      expect(bobMeetings.length).toBe(1); // Bob�� �섎굹�� 紐⑥엫 �앹꽦
-      expect(bobMeetings[0].title).toBe('Lunch Meeting');
-      expect(bobMeetings[0].isParticipant).toBe(true);
-
-      // 5�④퀎: Charlie�� 紐⑥엫 議고쉶
-      const charlieMeetings = await MeetingService.getMeetings(3); // Charlie�� �ъ슜�� ID
-      expect(charlieMeetings.length).toBe(2); // Charlie�� �� 紐⑥엫�� 李몄뿬
-      const meetingTitles = charlieMeetings.map(meeting => meeting.title);
-      expect(meetingTitles).toContain('Morning Meeting');
-      expect(meetingTitles).toContain('Lunch Meeting');
-
-      // 異붽� 寃�利�: 媛� �ъ슜�먯쓽 �ㅼ�以꾩쓣 �뺤씤�섏뿬 異⑸룎�� �녿뒗吏� �뺤씤
-      const aliceSchedules = await Schedule.findAll({ where: { user_id: 1 } });
-      expect(aliceSchedules.length).toBe(11); // Morning Meeting: 10-20
-
-      const bobSchedules = await Schedule.findAll({ where: { user_id: 2 } });
-      expect(bobSchedules.length).toBe(11); // Lunch Meeting: 30-40
-
-      const charlieSchedules = await Schedule.findAll({ where: { user_id: 3 } });
-      expect(charlieSchedules.length).toBe(22); // �� 紐⑥엫, 媛� 紐⑥엫留덈떎 11媛쒖쓽 �ㅼ�以� (10~20, 30~40)
-  });
+    beforeEach(async () => {
+        // �곗씠�곕쿋�댁뒪 珥덇린��
+        await MeetingParticipant.destroy({ where: {} });
+        await Meeting.destroy({ where: {} });
+        await Schedule.destroy({ where: {} });
+        await User.destroy({ where: {} });
+
+        // �붾� �ъ슜�� �앹꽦
+        await User.bulkCreate([
+            { id: 1, name: 'Alice', email: 'alice@example.com' },
+            { id: 2, name: 'Bob', email: 'bob@example.com' },
+            { id: 3, name: 'Charlie', email: 'charlie@example.com' },
+        ]);
+    });
+
+    test('�ъ슜�먭� �щ윭 紐⑥엫�� 李몄뿬�섍퀬 �대� �뺥솗�� 議고쉶�� �� �덉뼱�� �쒕떎', async () => {
+        // 1�④퀎: 寃뱀튂吏� �딅뒗 �쒓컙���� 紐⑥엫 �앹꽦
+        const meetingData1 = {
+            title: 'Morning Meeting',
+            description: 'Morning planning meeting.',
+            time_idx_start: 10,
+            time_idx_end: 20,
+            location: 'Room A',
+            time_idx_deadline: 8,
+            type: 'OPEN',
+            created_by: 1, // Alice媛� 紐⑥엫 �앹꽦
+        };
+
+        const meetingData2 = {
+            title: 'Lunch Meeting',
+            description: 'Lunch and discussion.',
+            time_idx_start: 30,
+            time_idx_end: 40,
+            location: 'Room B',
+            time_idx_deadline: 28,
+            type: 'OPEN',
+            created_by: 2, // Bob�� 紐⑥엫 �앹꽦
+        };
+
+        const meeting1 = await MeetingService.createMeeting(meetingData1);
+        const meeting2 = await MeetingService.createMeeting(meetingData2);
+
+        // 紐⑥엫 �앹꽦 �뺤씤
+        expect(meeting1).toBeDefined();
+        expect(meeting2).toBeDefined();
+
+        // 2�④퀎: Charlie媛� �� 紐⑥엫�� 李몄뿬
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5); // 留덇컧 �쒓컙�� 珥덇낵�섏� �딅룄濡� �ㅼ젙
+        await MeetingService.joinMeeting(meeting1.meeting_id, 3); // Charlie媛� Morning Meeting 李몄뿬
+        await MeetingService.joinMeeting(meeting2.meeting_id, 3); // Charlie媛� Lunch Meeting 李몄뿬
+
+        // 3�④퀎: Charlie�� 李몄뿬 紐⑥엫 議고쉶
+        const charlieMeetings = await MeetingService.getMeetings(3); // Charlie�� �ъ슜�� ID
+        expect(charlieMeetings).toBeDefined();
+        expect(Array.isArray(charlieMeetings)).toBe(true);
+        expect(charlieMeetings.length).toBe(2); // Charlie�� 2媛쒖쓽 紐⑥엫�� 李몄뿬
+
+        // 媛� 紐⑥엫�� �몃� �뺣낫 �뺤씤
+        const morningMeeting = charlieMeetings.find(meeting => meeting.title === 'Morning Meeting');
+        const lunchMeeting = charlieMeetings.find(meeting => meeting.title === 'Lunch Meeting');
+
+        expect(morningMeeting).toBeDefined();
+        expect(morningMeeting.creatorName).toBe('Alice');
+        expect(morningMeeting.isParticipant).toBe(true);
+
+        expect(lunchMeeting).toBeDefined();
+        expect(lunchMeeting.creatorName).toBe('Bob');
+        expect(lunchMeeting.isParticipant).toBe(true);
+
+        // 異붽� 寃�利�: 媛� 紐⑥엫�� ���� Charlie�� �ㅼ�以꾩씠 �щ컮瑜닿쾶 �앹꽦�섏뿀�붿� �뺤씤
+        const charlieSchedules = await Schedule.findAll({ where: { user_id: 3 } });
+        expect(charlieSchedules.length).toBe(2 * (20 - 10 + 1)); // �� 紐⑥엫, 媛� 紐⑥엫留덈떎 11媛쒖쓽 �ㅼ�以� (10~20, 30~40)
+
+        // 以묐났 �ㅼ�以꾩씠 �녿뒗吏� �뺤씤
+        const timeIndicesMorning = charlieSchedules
+            .filter(schedule => schedule.title === `踰덇컻 紐⑥엫: ${meetingData1.title}`)
+            .map(schedule => schedule.time_idx);
+        const timeIndicesLunch = charlieSchedules
+            .filter(schedule => schedule.title === `踰덇컻 紐⑥엫: ${meetingData2.title}`)
+            .map(schedule => schedule.time_idx);
+
+        // Morning Meeting�� �쒓컙�� �뺤씤
+        for (let i = 10; i <= 20; i++) {
+            expect(timeIndicesMorning).toContain(i);
+        }
+
+        // Lunch Meeting�� �쒓컙�� �뺤씤
+        for (let i = 30; i <= 40; i++) {
+            expect(timeIndicesLunch).toContain(i);
+        }
+    });
+
+    test('媛� �ъ슜�먯쓽 紐⑥엫�� �뺥솗�� 議고쉶�댁빞 �쒕떎', async () => {
+        // 1�④퀎: 寃뱀튂吏� �딅뒗 �쒓컙���� 紐⑥엫 �앹꽦
+        const meetingData1 = {
+            title: 'Morning Meeting',
+            time_idx_start: 10,
+            time_idx_end: 20,
+            location: 'Room A',
+            time_idx_deadline: 8,
+            type: 'OPEN',
+            created_by: 1
+        };
+
+        const meetingData2 = {
+            title: 'Lunch Meeting',
+            time_idx_start: 30,
+            time_idx_end: 40,
+            location: 'Room B',
+            time_idx_deadline: 28,
+            type: 'OPEN',
+            created_by: 2
+        };
+
+        const meeting1 = await MeetingService.createMeeting(meetingData1);
+        const meeting2 = await MeetingService.createMeeting(meetingData2);
+
+        // 2�④퀎: Charlie媛� �� 紐⑥엫�� 李몄뿬
+        jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(5);
+        await MeetingService.joinMeeting(meeting1.meeting_id, 3);
+        await MeetingService.joinMeeting(meeting2.meeting_id, 3);
+
+        // 3�④퀎: 媛� �ъ슜�먯쓽 紐⑥엫 議고쉶
+        const aliceMeetings = await MeetingService.getMeetings(1);
+        const bobMeetings = await MeetingService.getMeetings(2);
+        const charlieMeetings = await MeetingService.getMeetings(3);
+
+        // 紐⑤뱺 誘명똿�� 議고쉶�섏뼱�� ��
+        expect(aliceMeetings.length).toBe(2);
+        expect(bobMeetings.length).toBe(2);
+        expect(charlieMeetings.length).toBe(2);
+
+        // 李멸� �щ� �뺤씤
+        const aliceMorningMeeting = aliceMeetings.find(m => m.title === 'Morning Meeting');
+        expect(aliceMorningMeeting.isParticipant).toBe(true);
+
+        const bobLunchMeeting = bobMeetings.find(m => m.title === 'Lunch Meeting');
+        expect(bobLunchMeeting.isParticipant).toBe(true);
+
+        // Charlie�� �� 誘명똿 紐⑤몢 李멸�
+        expect(charlieMeetings.every(m => m.isParticipant)).toBe(true);
+    });
 });
 
-- 
GitLab


From 454bf03649f7f7642a376b5f3672b08b344fcf1b 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: Mon, 25 Nov 2024 20:36:10 +0900
Subject: [PATCH 04/14] =?UTF-8?q?fix:=20=EC=A4=91=EB=B3=B5=20=EC=BD=94?=
 =?UTF-8?q?=EB=93=9C=20=EC=82=AD=EC=A0=9C=20/=20=EA=B3=A0=EC=A0=95=20?=
 =?UTF-8?q?=EC=8B=9C=EA=B0=84=EB=8C=80=20=EC=84=A4=EC=A0=95=20=EB=B3=80?=
 =?UTF-8?q?=EA=B2=BD=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.js | 123 +------------------------------------
 1 file changed, 1 insertion(+), 122 deletions(-)

diff --git a/services/meetingService.js b/services/meetingService.js
index 653b73a..befefae 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -253,7 +253,7 @@ class MeetingService {
             {
               userId: userId,
               title: `踰덇컻 紐⑥엫: ${meeting.title}`,
-              is_fixed: true,
+              is_fixed: false,
               events: events,
             },
             transaction
@@ -342,127 +342,6 @@ class MeetingService {
         await meeting.save();
         return meeting;
     }
-
-  
-    async joinMeeting(meetingId, userId) {
-        const meeting = await Meeting.findByPk(meetingId);
-        console.log(`李몄뿬�섎젮�� 紐⑥엫: ${JSON.stringify(meeting)}`);
-        if (!meeting) {
-            throw new Error('紐⑥엫�� 李얠쓣 �� �놁뒿�덈떎.');
-        }
-        if (meeting.type === 'CLOSE') {
-            throw new Error('�대� 留덇컧�� 紐⑥엫�낅땲��.');
-        }
-        if (meeting.time_idx_deadline !== undefined) {
-            const currentTimeIdx = this.getCurrentTimeIdx(); // �꾩옱 �쒓컙 �몃뜳��
-            if (currentTimeIdx >= meeting.time_idx_deadline) {
-                throw new Error('李멸� �좎껌�� 留덇컧�섏뿀�듬땲��.');
-            }
-        }
-        const existingParticipant = await MeetingParticipant.findOne({
-            where: { meeting_id: meetingId, user_id: userId },
-        });
-        if (existingParticipant) {
-            throw new Error('�대� 李멸��� �ъ슜�먯엯�덈떎.');
-        }
-
-        // �몃옖��뀡�� �ъ슜�섏뿬 李멸��� 異붽� 諛� �ㅼ�以� �낅뜲�댄듃瑜� �먯옄�곸쑝濡� 泥섎━
-        await sequelize.transaction(async (transaction) => {
-          // �ㅼ�以� 異⑸룎 �뺤씤
-          // �꾩옱 �몄썝 �� �뺤씤
-          if (meeting.cur_num >= meeting.max_num) {
-            throw new Error("紐⑥엫 �몄썝�� 紐⑤몢 李쇱뒿�덈떎.");
-          }
-
-          const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
-            userId,
-            meeting.time_idx_start,
-            meeting.time_idx_end,
-            transaction
-          );
-          console.log(`�ㅼ�以� 異⑸룎 寃곌낵: ${hasConflict}`);
-          if (hasConflict) {
-            throw new Error("�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ 紐⑥엫�� 李멸��섏꽭��.");
-          }
-
-          // 李멸��� 異붽�
-          await MeetingParticipant.create(
-            { meeting_id: meetingId, user_id: userId },
-            { transaction }
-          );
-
-          // �ㅼ�以� �앹꽦 (紐⑥엫 �쒓컙 踰붿쐞 �� 紐⑤뱺 time_idx�� ���� �앹꽦)
-          const events = [];
-          for (
-            let idx = meeting.time_idx_start;
-            idx <= meeting.time_idx_end;
-            idx++
-          ) {
-            events.push({ time_idx: idx });
-          }
-          await ScheduleService.createSchedules(
-            {
-              userId: userId,
-              title: `踰덇컻 紐⑥엫: ${meeting.title}`,
-              is_fixed: true,
-              events: events,
-            },
-            transaction
-          );
-
-          // 梨꾪똿諛� 李멸� (MongoDB)
-          const user = await User.findOne({
-            where: { id: userId },
-            transaction,
-          });
-          const chatRoom = await ChatRooms.findOne({
-            chatRoomId: meeting.chatRoomId,
-          });
-          if (chatRoom && !chatRoom.participants.includes(user.name)) {
-            chatRoom.participants.push(user.name);
-            chatRoom.isOnline.set(user.name, true);
-            chatRoom.lastReadAt.set(user.name, new Date());
-            chatRoom.lastReadLogId.set(user.name, null);
-            await chatRoom.save();
-          }
-
-          // �꾩옱 �몄썝 �� 利앷�
-          await meeting.increment("cur_num", { by: 1, transaction });
-        await Meeting.sequelize.transaction(async (transaction) => {
-            const hasConflict = await ScheduleService.checkScheduleOverlap(
-                userId,
-                new Date(meeting.start_time),
-                new Date(meeting.end_time)
-            );
-            if (hasConflict) {
-                throw new Error('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ 紐⑥엫�� 李멸��섏꽭��.');
-            }
-
-            await MeetingParticipant.create({ meeting_id: meetingId, user_id: userId }, { transaction });
-
-            await ScheduleService.createSchedule({
-                userId,
-                title: `踰덇컻 紐⑥엫: ${meeting.title}`,
-                start_time: new Date(meeting.start_time),
-                end_time: new Date(meeting.end_time),
-                is_fixed: true,
-            });
-
-            // �ъ슜�먯� FCM �좏겙 議고쉶
-            const user = await this._findUserWithFcmTokens(userId);
-            const userFcmTokens = user.fcmTokenList.map((fcmToken) => fcmToken.token);
-
-            const chatRoom = await ChatRoom.findOne({ chatRoomId: meeting.chatRoomId });
-
-            if (chatRoom) {
-                console.log("梨꾪똿諛� 李얠쓬");
-                this._addParticipantToChatRoom(chatRoom, user, userFcmTokens);
-            }
-        });
-    });
-    }
-    
-
     
     async getMeetingDetail(meetingId, userId) {
         const meeting = await Meeting.findByPk(meetingId, {
-- 
GitLab


From 8eda3e9c25b1c6eb0253b278c792a7d8d0ed614f 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: Mon, 25 Nov 2024 20:50:08 +0900
Subject: [PATCH 05/14] =?UTF-8?q?refactor:=20friend=20pagination=20?=
 =?UTF-8?q?=EB=B0=A9=EC=8B=9D=20=EC=88=98=EC=A0=95=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 controllers/friendController.js | 18 +++++++++++++++---
 routes/friend.js                |  2 +-
 services/friendService.js       | 21 +++++++++++++++------
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/controllers/friendController.js b/controllers/friendController.js
index 8f385c7..c3eb251 100644
--- a/controllers/friendController.js
+++ b/controllers/friendController.js
@@ -137,15 +137,27 @@ class friendController {
 
     /**
      * 移쒓뎄 紐⑸줉 議고쉶
-     * GET /api/friend/all/:offset
+     * GET /api/friend/all?page=1&size=20
      */
     async getFriendList(req, res) {
         try {
             const userId = req.user.id;
-            const friends = await FriendService.getFriendList(userId,20,req.param);
+            const page = parseInt(req.query.page) || 0;
+            const size = parseInt(req.query.size) || 20;
+            
+            const friends = await FriendService.getFriendList(userId, {
+                limit: size,
+                offset: page * size
+            });
+
             return res.status(200).json({
                 success: true,
-                data: friends
+                data: {
+                    content: friends,
+                    page: page,
+                    size: size,
+                    hasNext: friends.length === size 
+                }
             });
         } catch (error) {
             return res.status(500).json({
diff --git a/routes/friend.js b/routes/friend.js
index 53145a9..6061959 100644
--- a/routes/friend.js
+++ b/routes/friend.js
@@ -37,7 +37,7 @@ router.post('/request/:friendId/reject', FriendController.rejectRequest);
 
 /**
  * 移쒓뎄 紐⑸줉 議고쉶
- * GET /api/friend/all
+ * GET /api/friend/all?page=1&size=20
  */
 router.get('/all', FriendController.getFriendList);
 
diff --git a/services/friendService.js b/services/friendService.js
index bb995bb..d35b3c7 100644
--- a/services/friendService.js
+++ b/services/friendService.js
@@ -191,7 +191,9 @@ class FriendService {
      * @param {number} offset - �섏씠吏� �ㅽ봽��
      * @returns {Promise<Array<FriendListDTO>>} - 移쒓뎄 紐⑸줉 DTO 諛곗뿴
      */
-    async getFriendList(userId, limit = 20, offset = 0) {
+    async getFriendList(userId, pagination) {
+        const { limit = 20, offset = 0 } = pagination;
+    
         const friends = await Friend.findAll({
             where: {
                 [Op.or]: [
@@ -212,13 +214,20 @@ class FriendService {
                     attributes: ['id', 'name', 'email']
                 }
             ],
-            order: [['id', 'ASC']], 
-            limit,
+            order: [['id', 'ASC']],
+            limit: limit + 1, // �ㅼ쓬 �섏씠吏� 議댁옱 �щ� �뺤씤�� �꾪빐 1媛� �� 議고쉶
             offset
         });
-
-
-        return friends.map(friend => new FriendListDTO(friend, userId));
+    
+        const hasNext = friends.length > limit;
+        const content = friends.slice(0, limit).map(friend => new FriendListDTO(friend, userId));
+    
+        return {
+            content,
+            page: offset / limit,
+            size: limit,
+            hasNext
+        };
     }
 
     /**
-- 
GitLab


From a0e5e827e4673706d6c6f563fa25703320786e5b 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: Mon, 25 Nov 2024 20:51:21 +0900
Subject: [PATCH 06/14] =?UTF-8?q?refactor:=20friend=20pagination=20?=
 =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=ED=85=8C?=
 =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95=20?=
 =?UTF-8?q?(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/friendService.test.js | 81 ++++++++++++++++++++++------------
 1 file changed, 54 insertions(+), 27 deletions(-)

diff --git a/services/friendService.test.js b/services/friendService.test.js
index 02394ee..2822a25 100644
--- a/services/friendService.test.js
+++ b/services/friendService.test.js
@@ -143,50 +143,77 @@ describe('Friend Service', () => {
     });
 
     describe('getFriendList', () => {
-        test('should retrieve friend list with correct pagination', async () => {
+        beforeEach(async () => {
             await friendService.sendFriendRequest(1, 2);
             await friendService.acceptFriendRequest(2, 1);
-
             await friendService.sendFriendRequest(1, 3);
             await friendService.acceptFriendRequest(3, 1);
-
+    
             // 異붽� �붾��곗씠�� �앹꽦
             for (let i = 4; i <= 23; i++) {
-                // Create dummy users
                 await User.create({
                     id: i,
                     name: `User${i}`,
                     email: `user${i}@example.com`,
                 });
-
-                // Alice�� 移쒓뎄留브린
                 await friendService.sendFriendRequest(1, i);
                 await friendService.acceptFriendRequest(i, 1);
             }
-
-            // Alice 移쒓뎄: Bob (2), Charlie (3), User4遺��� User23源뚯� (珥� 22紐�)
-            const limit = 5;
-            const offset = 0;
-            const friendsPage1 = await friendService.getFriendList(1, limit, offset);
-            expect(friendsPage1.length).toBe(limit);
-            const expectedNamesPage1 = ['Bob', 'Charlie', 'User4', 'User5', 'User6'];
-            const receivedNamesPage1 = friendsPage1.map(friend => friend.friendInfo.name);
-            expectedNamesPage1.forEach(name => {
-                expect(receivedNamesPage1).toContain(name);
+        });
+    
+        test('�묒� size濡� �щ윭 �섏씠吏� 議고쉶', async () => {
+            const size = 10;
+            
+            // 泥� �섏씠吏�
+            const page1 = await friendService.getFriendList(1, {
+                limit: size,
+                offset: 0
             });
-
-            const friendsPage2 = await friendService.getFriendList(1, limit, limit);
-            expect(friendsPage2.length).toBe(limit);
-            const expectedNamesPage2 = ['User7', 'User8', 'User9', 'User10', 'User11'];
-            const receivedNamesPage2 = friendsPage2.map(friend => friend.friendInfo.name);
-            expectedNamesPage2.forEach(name => {
-                expect(receivedNamesPage2).toContain(name);
+            expect(page1.content.length).toBe(size);
+            expect(page1.hasNext).toBe(true);
+            
+            // �� 踰덉㎏ �섏씠吏�
+            const page2 = await friendService.getFriendList(1, {
+                limit: size,
+                offset: size
+            });
+            expect(page2.content.length).toBe(size);
+            expect(page2.hasNext).toBe(true);
+            
+            // 留덉�留� �섏씠吏�
+            const page3 = await friendService.getFriendList(1, {
+                limit: size,
+                offset: size * 2
             });
+            expect(page3.content.length).toBe(2);
+            expect(page3.hasNext).toBe(false);
         });
-
-        test('should return empty array when user has no friends', async () => {
-            const friends = await friendService.getFriendList(999); // Non-existing user
-            expect(friends.length).toBe(0);
+    
+        test('�섏씠吏� �쒖꽌 寃�利�', async () => {
+            const size = 5;
+            const page1 = await friendService.getFriendList(1, {
+                limit: size,
+                offset: 0
+            });
+            const page2 = await friendService.getFriendList(1, {
+                limit: size,
+                offset: size
+            });
+    
+            const names1 = page1.content.map(friend => friend.friendInfo.name);
+            const names2 = page2.content.map(friend => friend.friendInfo.name);
+    
+            expect(names1).toEqual(['Bob', 'Charlie', 'User4', 'User5', 'User6']);
+            expect(names2).toEqual(['User7', 'User8', 'User9', 'User10', 'User11']);
+        });
+    
+        test('議댁옱�섏� �딅뒗 �섏씠吏� 議고쉶', async () => {
+            const response = await friendService.getFriendList(1, {
+                limit: 20,
+                offset: 100
+            });
+            expect(response.content).toHaveLength(0);
+            expect(response.hasNext).toBe(false);
         });
     });
 
-- 
GitLab


From fc0d45aa53b57fb34175883feb98d056a18bc8f0 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: Mon, 25 Nov 2024 22:01:32 +0900
Subject: [PATCH 07/14] =?UTF-8?q?refactor:=20meeting=20pagination=20?=
 =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 controllers/meetingController.js | 27 ++++++++++++++-----
 services/meetingService.js       | 46 ++++++++++++++++++++------------
 2 files changed, 50 insertions(+), 23 deletions(-)

diff --git a/controllers/meetingController.js b/controllers/meetingController.js
index d85e788..4363b41 100644
--- a/controllers/meetingController.js
+++ b/controllers/meetingController.js
@@ -21,9 +21,9 @@ class MeetingController {
     async createMeeting(req, res) {
         try {
             const userId = req.user.id;
-            const meetingData = { 
-                ...req.body, 
-                created_by: userId 
+            const meetingData = {
+                ...req.body,
+                created_by: userId
             };
             const createMeetingDTO = new CreateMeetingRequestDTO(meetingData);
             createMeetingDTO.validate();
@@ -43,8 +43,23 @@ class MeetingController {
     async getMeetings(req, res) {
         try {
             const userId = req.user.id; // �몄쬆 誘몃뱾�⑥뼱瑜� �듯빐 �ㅼ젙�� �ъ슜�� ID
-            const meetings = await MeetingService.getMeetings(userId);
-            res.status(200).json(meetings);
+            const page = parseInt(req.query.page) || 0;
+            const size = parseInt(req.query.size) || 20;
+
+            const meetings = await MeetingService.getMeetings(userId, {
+                limit: size,
+                offset: page * size
+            });
+
+            res.status(200).json({
+                success: true,
+                data: {
+                    content: meetings.content,
+                    page: page,
+                    size: size,
+                    hasNext: meetings.hasNext
+                }
+            });
         } catch (err) {
             console.error('紐⑥엫 紐⑸줉 議고쉶 �ㅻ쪟:', err);
             res.status(500).json({ error: err.message || '紐⑥엫 紐⑸줉 議고쉶 �ㅽ뙣' });
@@ -77,7 +92,7 @@ class MeetingController {
             const userId = req.user.id; // �몄쬆 誘몃뱾�⑥뼱瑜� �듯빐 �ㅼ젙�� �ъ슜�� ID
 
             await MeetingService.joinMeeting(meetingId, userId);
-            
+
             res.status(200).json({ message: '紐⑥엫 諛� 梨꾪똿諛� 李멸� �꾨즺' });
         } catch (err) {
             console.error('紐⑥엫 李멸� �ㅻ쪟:', err);
diff --git a/services/meetingService.js b/services/meetingService.js
index befefae..bbc157f 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -281,7 +281,9 @@ class MeetingService {
     }
 
     
-    async getMeetings(userId) {
+    async getMeetings(userId, pagination) {
+        const { limit = 20, offset = 0 } = pagination;
+
         const meetings = await Meeting.findAll({
             attributes: [
                 'id',
@@ -307,26 +309,36 @@ class MeetingService {
                     as: 'creator',
                     attributes: ['name'],
                 }
-            ]
+            ],
+            order: [['createdAt', 'DESC']],
+            offset
         });
     
-        return Promise.all(meetings.map(async (meeting) => {
-            const isParticipant = await MeetingParticipant.findOne({
-                where: {
-                    meeting_id: meeting.id,
-                    user_id: userId
-                }
-            });
+        const hasNext = meetings.length > limit;
+        const content = await Promise.all(
+            meetings.slice(0, limit).map(async (meeting) => {
+                const isParticipant = await MeetingParticipant.findOne({
+                    where: {
+                        meeting_id: meeting.id,
+                        user_id: userId
+                    }
+                });
     
-            const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
-                userId,
-                meeting.time_idx_start,
-                meeting.time_idx_end
-            );
+                const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
+                    userId,
+                    meeting.time_idx_start,
+                    meeting.time_idx_end
+                );
+    
+                const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
+                return new MeetingResponseDTO(meeting, !!isParticipant, hasConflict, creatorName);
+            })
+        );
     
-            const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
-            return new MeetingResponseDTO(meeting, !!isParticipant, hasConflict, creatorName);
-        }));
+        return {
+            content,
+            hasNext
+        };
     }
 
   
-- 
GitLab


From 1ac37b1b4fdc5545be1a0eabdfdc90be908bbe38 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: Mon, 25 Nov 2024 22:01:50 +0900
Subject: [PATCH 08/14] =?UTF-8?q?test,=20refactor:=20meeting=20paginaton?=
 =?UTF-8?q?=20=EC=A0=81=EC=9A=A9=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.test.js | 23 ++++++++++++-----------
 1 file changed, 12 insertions(+), 11 deletions(-)

diff --git a/services/meetingService.test.js b/services/meetingService.test.js
index 8615ca5..0ba48c6 100644
--- a/services/meetingService.test.js
+++ b/services/meetingService.test.js
@@ -117,7 +117,7 @@ describe('MeetingService - �꾩껜 誘명똿 議고쉶 �뚯뒪��', () => {
         await MeetingService.createMeeting(meetingData1);
         await MeetingService.createMeeting(meetingData2);
 
-        const meetings = await MeetingService.getMeetings(1);
+        const {content: meetings} = await MeetingService.getMeetings(1, {limit: 20, offset: 0});
 
         expect(meetings.length).toBe(2);
 
@@ -178,9 +178,9 @@ describe('MeetingService - �꾩껜 誘명똿 議고쉶 �뚯뒪��', () => {
             events: [{ time_idx: 51 }]
         });
 
-        const aliceMeetings = await MeetingService.getMeetings(1);
-        const bobMeetings = await MeetingService.getMeetings(2);
-        const charlieMeetings = await MeetingService.getMeetings(3);
+        const {content: aliceMeetings } = await MeetingService.getMeetings(1, {limit: 20, offset: 0});
+        const {content: bobMeetings } = await MeetingService.getMeetings(2, {limit: 20, offset: 0});
+        const {content: charlieMeetings } = await MeetingService.getMeetings(3, {limit: 20, offset: 0});
 
         expect(aliceMeetings[0].isScheduleConflict).toBe(false);
         expect(bobMeetings[0].isScheduleConflict).toBe(true);
@@ -232,7 +232,7 @@ describe('MeetingService - Integration: createMeeting, joinMeeting, getMeetings'
         await MeetingService.joinMeeting(createdMeeting.meeting_id, 3); // Charlie joins
 
         // Step 3: Retrieve meetings for Alice (creator)
-        const aliceMeetings = await MeetingService.getMeetings(1);
+        const {content: aliceMeetings } = await MeetingService.getMeetings(1, {limit: 20, offset: 0});
         expect(aliceMeetings).toBeDefined();
         expect(aliceMeetings.length).toBe(1);
 
@@ -242,7 +242,7 @@ describe('MeetingService - Integration: createMeeting, joinMeeting, getMeetings'
         expect(aliceMeeting.isParticipant).toBe(true);
 
         // Step 4: Retrieve meetings for Bob (participant)
-        const bobMeetings = await MeetingService.getMeetings(2);
+        const {content: bobMeetings } = await MeetingService.getMeetings(2, {limit: 20, offset: 0});
         expect(bobMeetings).toBeDefined();
         expect(bobMeetings.length).toBe(1);
 
@@ -252,7 +252,7 @@ describe('MeetingService - Integration: createMeeting, joinMeeting, getMeetings'
         expect(bobMeeting.isParticipant).toBe(true);
 
         // Step 5: Retrieve meetings for Charlie (participant)
-        const charlieMeetings = await MeetingService.getMeetings(3);
+        const {content: charlieMeetings } = await MeetingService.getMeetings(3, {limit: 20, offset: 0});
         expect(charlieMeetings).toBeDefined();
         expect(charlieMeetings.length).toBe(1);
 
@@ -387,7 +387,7 @@ describe('MeetingService2', () => {
         await MeetingService.joinMeeting(meeting2.meeting_id, 3); // Charlie媛� Lunch Meeting 李몄뿬
 
         // 3�④퀎: Charlie�� 李몄뿬 紐⑥엫 議고쉶
-        const charlieMeetings = await MeetingService.getMeetings(3); // Charlie�� �ъ슜�� ID
+        const {content: charlieMeetings } = await MeetingService.getMeetings(3, {limit: 20, offset: 0}); // Charlie�� �ъ슜�� ID
         expect(charlieMeetings).toBeDefined();
         expect(Array.isArray(charlieMeetings)).toBe(true);
         expect(charlieMeetings.length).toBe(2); // Charlie�� 2媛쒖쓽 紐⑥엫�� 李몄뿬
@@ -458,9 +458,10 @@ describe('MeetingService2', () => {
         await MeetingService.joinMeeting(meeting2.meeting_id, 3);
 
         // 3�④퀎: 媛� �ъ슜�먯쓽 紐⑥엫 議고쉶
-        const aliceMeetings = await MeetingService.getMeetings(1);
-        const bobMeetings = await MeetingService.getMeetings(2);
-        const charlieMeetings = await MeetingService.getMeetings(3);
+        const pagination = {limit: 20, offset:0 };
+        const {content: aliceMeetings} = await MeetingService.getMeetings(1, pagination);
+        const {content: bobMeetings} = await MeetingService.getMeetings(2, pagination);
+        const {content: charlieMeetings} = await MeetingService.getMeetings(3, pagination);
 
         // 紐⑤뱺 誘명똿�� 議고쉶�섏뼱�� ��
         expect(aliceMeetings.length).toBe(2);
-- 
GitLab


From c36ad889fc75350aa30d1fe048865e08597400e1 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: Tue, 26 Nov 2024 15:12:02 +0900
Subject: [PATCH 09/14] =?UTF-8?q?feat:=20=EB=82=B4=EA=B0=80=20=EC=B0=B8?=
 =?UTF-8?q?=EC=97=AC=ED=95=9C=20=EB=AF=B8=ED=8C=85=20=EB=AA=A9=EB=A1=9D=20?=
 =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.js | 68 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 68 insertions(+)

diff --git a/services/meetingService.js b/services/meetingService.js
index bbc157f..b529db0 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -341,6 +341,74 @@ class MeetingService {
         };
     }
 
+    async getMyMeetings(userId, pagination) {
+        const { limit = 20, offset = 0 } = pagination;
+    
+        const meetings = await Meeting.findAll({
+            attributes: [
+                'id',
+                'title',
+                'description',
+                'time_idx_start',
+                'time_idx_end',
+                'location',
+                'time_idx_deadline',
+                'type',
+                'max_num',
+                'cur_num',
+            ],
+            include: [
+                {
+                    model: MeetingParticipant,
+                    as: 'participants',
+                    where: { user_id: userId }, 
+                    attributes: [],
+                },
+                {
+                    model: User,
+                    as: 'creator',
+                    attributes: ['name'],
+                }
+            ],
+            where: {
+                [Op.or]: [
+                    { created_by: userId },  
+                    { '$participants.user_id$': userId }  
+                ]
+            },
+            order: [['createdAt', 'DESC']],
+            offset
+        });
+    
+        const hasNext = meetings.length > limit;
+        const content = await Promise.all(
+            meetings.slice(0, limit).map(async (meeting) => {
+                const isParticipant = await MeetingParticipant.findOne({
+                    where: {
+                        meeting_id: meeting.id,
+                        user_id: userId
+                    }
+                });
+    
+                const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
+                    userId,
+                    meeting.time_idx_start,
+                    meeting.time_idx_end
+                );
+    
+                const creatorName = meeting.creator ? meeting.creator.name : 'Unknown';
+                return new MeetingResponseDTO(meeting, !!isParticipant, hasConflict, creatorName);
+            })
+        );
+    
+        return {
+            content,
+            hasNext
+        };
+    }
+
+    
+
   
     async closeMeeting(meetingId) {
         const meeting = await Meeting.findByPk(meetingId);
-- 
GitLab


From c089671262e1c7fac47018181f0fc0895019b2da 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: Tue, 26 Nov 2024 15:12:23 +0900
Subject: [PATCH 10/14] =?UTF-8?q?feat:=20=EB=AF=B8=ED=8C=85=20=ED=83=88?=
 =?UTF-8?q?=ED=87=B4=ED=95=98=EA=B8=B0=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.js | 77 ++++++++++++++++++++++++++++++--------
 1 file changed, 61 insertions(+), 16 deletions(-)

diff --git a/services/meetingService.js b/services/meetingService.js
index b529db0..5cfe533 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -407,22 +407,6 @@ class MeetingService {
         };
     }
 
-    
-
-  
-    async closeMeeting(meetingId) {
-        const meeting = await Meeting.findByPk(meetingId);
-        if (!meeting) {
-            throw new Error('紐⑥엫�� 李얠쓣 �� �놁뒿�덈떎.');
-        }
-        if (meeting.type === 'CLOSE') {
-            throw new Error('�대� 留덇컧�� 紐⑥엫�낅땲��.');
-        }
-        meeting.type = 'CLOSE';
-        await meeting.save();
-        return meeting;
-    }
-    
     async getMeetingDetail(meetingId, userId) {
         const meeting = await Meeting.findByPk(meetingId, {
             include: [
@@ -530,6 +514,67 @@ class MeetingService {
         // ����
         chatRoom.save();
     }
+    
+    async leaveMeeting(meetingId, userId) {
+        const meeting = await Meeting.findByPk(meetingId);
+        if (!meeting) {
+            throw new Error('紐⑥엫�� 李얠쓣 �� �놁뒿�덈떎.');
+        }
+    
+        await sequelize.transaction(async (transaction) => {
+            // 李멸��� �뺤씤
+            const participant = await MeetingParticipant.findOne({
+                where: {
+                    meeting_id: meetingId,
+                    user_id: userId
+                },
+                transaction
+            });
+    
+            if (!participant) {
+                throw new Error('李멸��섏� �딆� 紐⑥엫�낅땲��.');
+            }
+    
+            // �앹꽦�먮뒗 �덊눜�� �� �놁쓬
+            if (meeting.created_by === userId) {
+                throw new Error('紐⑥엫 �앹꽦�먮뒗 �덊눜�� �� �놁뒿�덈떎.');
+            }
+    
+            // 李멸��� �쒓굅
+            await MeetingParticipant.destroy({
+                where: {
+                    meeting_id: meetingId,
+                    user_id: userId
+                },
+                transaction
+            });
+    
+            // 愿��� �ㅼ�以� ��젣
+            await Schedule.destroy({
+                where: {
+                    user_id: userId,
+                    title: `踰덇컻 紐⑥엫: ${meeting.title}`,
+                    time_idx: {
+                        [Op.between]: [meeting.time_idx_start, meeting.time_idx_end]
+                    }
+                },
+                transaction
+            });
+    
+            // 梨꾪똿諛⑹뿉�� �쒓굅
+            const chatRoom = await ChatRooms.findOne({
+                chatRoomId: meeting.chatRoomId
+            });
+            if (chatRoom) {
+                const user = await User.findByPk(userId);
+                chatRoom.participants = chatRoom.participants.filter(p => p !== user.name);
+                await chatRoom.save();
+            }
+    
+            // �꾩옱 �몄썝 �� 媛먯냼
+            await meeting.decrement('cur_num', { by: 1, transaction });
+        });
+    }
 }
 
 module.exports = new MeetingService();
\ No newline at end of file
-- 
GitLab


From 1decbb0b21f6784aeb9b313029e650889faa879d 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: Tue, 26 Nov 2024 16:27:27 +0900
Subject: [PATCH 11/14] =?UTF-8?q?test:=20=ED=86=B5=ED=95=A9=20Test=20?=
 =?UTF-8?q?=EC=B4=88=EC=95=88=20=EC=9E=91=EC=84=B1=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/integration.test.js | 261 +++++++++++++++++++++++++++++++++++
 1 file changed, 261 insertions(+)
 create mode 100644 services/integration.test.js

diff --git a/services/integration.test.js b/services/integration.test.js
new file mode 100644
index 0000000..6375ce7
--- /dev/null
+++ b/services/integration.test.js
@@ -0,0 +1,261 @@
+// test/integration.test.js
+const sequelize = require('../config/sequelize');
+const { User, Friend, Meeting, Schedule, MeetingParticipant, ChatRooms } = require('../models');
+const FriendService = require('../services/friendService');
+const MeetingService = require('../services/meetingService');
+const ScheduleService = require('../services/scheduleService');
+
+describe('System Integration Test', () => {
+  beforeAll(async () => {
+    await sequelize.sync({ force: true });
+
+    jest.spyOn(ChatRooms.prototype, 'save').mockResolvedValue(undefined);
+    jest.spyOn(ChatRooms, 'findOne').mockResolvedValue({
+      participants: [],
+      isOnline: new Map(),
+      lastReadAt: new Map(),
+      lastReadLogId: new Map(),
+      save: jest.fn().mockResolvedValue(true),
+    });
+
+    // �뚯뒪�몄슜 �ъ슜�� �앹꽦
+    await User.bulkCreate([
+      { id: 1, name: 'Alice', email: 'alice@example.com' },
+      { id: 2, name: 'Bob', email: 'bob@example.com' },
+      { id: 3, name: 'Charlie', email: 'charlie@example.com' }
+    ]);
+
+    // �깅뒫 痢≪젙�� �꾪븳 �쒖옉 �쒓컙 湲곕줉
+    console.time('Complete User Journey');
+  });
+
+  afterAll(async () => {
+    console.timeEnd('Complete User Journey');
+    jest.restoreAllMocks();
+    await sequelize.close();
+  });
+
+  /**
+   * �쒕굹由ъ삤 1
+   * 1. 移쒓뎄
+   * 2. �ㅼ�以� 愿�由�
+   * 3. 誘명똿
+   * 4. 議고쉶
+   */
+
+  test('Complete User Journey Scenario', async () => {
+    const pagination = { limit: 20, offset: 0 };
+    /**
+     * 1. 移쒓뎄
+     * 移쒓뎄 �붿껌/�섎씫/嫄곗젅
+     * 移쒓뎄 紐⑸줉 議고쉶
+     * 以묐났 移쒓뎄 �붿껌 諛⑹�
+     * ++ 移쒓뎄 �ㅼ�以� 蹂닿린
+     */
+    console.time('Friend Operations');
+    const aliceId = 1, bobId = 2, charlieId = 3;
+
+    await FriendService.sendFriendRequest(aliceId, bobId);
+    await FriendService.sendFriendRequest(aliceId, charlieId);
+
+    await FriendService.acceptFriendRequest(bobId, aliceId);
+    await FriendService.rejectFriendRequest(charlieId, aliceId);
+
+    const aliceFriends = await FriendService.getFriendList(aliceId, pagination);
+    expect(aliceFriends.content.length).toBe(1);
+    expect(aliceFriends.content[0].friendInfo.name).toBe('Bob');
+
+    await expect(
+      FriendService.sendFriendRequest(aliceId, bobId)
+    ).rejects.toThrow('Friend request already exists');
+
+    /**
+     * 2. �ㅼ�以� 愿�由�
+     * �ㅼ�以� �앹꽦/�섏젙/��젣
+     * �꾩껜 �ㅼ�以� 議고쉶
+     * �뱀젙 �ㅼ�以� 議고쉶
+     * ++ �섏씠吏��ㅼ씠�� �뺤씤
+     */
+    console.time('Schedule Operations');
+
+    // 2-1. �ㅼ�以� �앹꽦
+    const aliceSchedule = {
+      userId: aliceId,
+      title: '�섏뾽',
+      is_fixed: true,
+      events: [
+        { time_idx: 36 },
+        { time_idx: 37 },
+        { time_idx: 38 }
+      ]
+    };
+    const createdSchedules = await ScheduleService.createSchedules(aliceSchedule);
+    expect(createdSchedules.length).toBe(3);
+
+    // 2-2. �뱀젙 �ㅼ�以� 議고쉶
+    const specificSchedule = await ScheduleService.getScheduleByTimeIdx(aliceId, 36);
+    expect(specificSchedule.title).toBe('�섏뾽');
+    expect(specificSchedule.is_fixed).toBe(true);
+
+    // 2-3. �꾩껜 �ㅼ�以� 議고쉶
+    const allSchedules = await ScheduleService.getAllSchedules(aliceId);
+    expect(allSchedules.length).toBe(3);
+    expect(allSchedules.every(s => s.title === '�섏뾽')).toBe(true);
+
+    // 2-4. �ㅼ�以� �섏젙
+    const scheduleUpdates = [
+      { time_idx: 36, title: '以묒슂 �섏뾽', is_fixed: true }
+    ];
+    const updatedSchedules = await ScheduleService.updateSchedules(aliceId, scheduleUpdates);
+    expect(updatedSchedules[0].title).toBe('以묒슂 �섏뾽');
+
+    // 2-5. �섏젙�� �ㅼ�以� �뺤씤
+    const updatedAllSchedules = await ScheduleService.getAllSchedules(aliceId);
+    const updatedSchedule = updatedAllSchedules.find(s => s.time_idx === 36);
+    expect(updatedSchedule.title).toBe('以묒슂 �섏뾽');
+
+    // 2-6. �ㅼ�以� ��젣
+    const deleteResult = await ScheduleService.deleteSchedules(aliceId, [37]);
+    expect(deleteResult.deleted_time_idxs).toContain(37);
+
+    // 2-7. ��젣 �뺤씤
+    const remainingSchedules = await ScheduleService.getAllSchedules(aliceId);
+    expect(remainingSchedules.length).toBe(2);
+    expect(remainingSchedules.every(s => s.time_idx !== 37)).toBe(true);
+
+    // 2-8. 以묐났 �ㅼ�以� �앹꽦 �쒕룄
+    await expect(
+      ScheduleService.createSchedules({
+        userId: aliceId,
+        title: '以묐났 �ㅼ�以�',
+        is_fixed: true,
+        events: [{ time_idx: 36 }]
+      })
+    ).rejects.toThrow('Schedule overlaps with existing schedule');
+
+    console.timeEnd('Schedule Operations');
+
+
+    /**
+     * 3. 誘명똿 李멸�
+     * 誘명똿 �앹꽦/�ㅼ�以� �먮룞 �깅줉 ++ create �� �앹꽦�먯쓽 �ㅼ�以� �뺤씤 諛� 以묐났 泥댄겕
+     * 以묐났�� �쒓컙 李몄뿬 遺덇�
+     * 誘명똿 close (�앹꽦��)
+     * 誘명똿 �덊눜
+     * ++ 移쒓뎄 珥덈�
+     */
+    jest.spyOn(MeetingService, 'getCurrentTimeIdx').mockReturnValue(30);
+
+    /**
+     * 3. 誘명똿 李멸� �쒕굹由ъ삤
+     */
+    console.time('Meeting Operations');
+
+    // 3-1. 誘명똿 �앹꽦 諛� �ㅼ�以� �먮룞 �깅줉
+    const meetingData = {
+      title: '�ㅽ꽣�� 紐⑥엫',
+      time_idx_start: 36,
+      time_idx_end: 38,
+      created_by: bobId,
+      type: 'OPEN',
+      time_idx_deadline: 35,
+      location: 'Room A'
+    };
+
+    const meeting = await MeetingService.createMeeting(meetingData);
+
+    const bobSchedules = await Schedule.findAll({
+      where: {
+        user_id: bobId,
+        title: `踰덇컻 紐⑥엫: ${meetingData.title}`
+      }
+    });
+    expect(bobSchedules.length).toBe(3); // 36-38 �쒓컙��
+
+    // 3-2. �ㅼ�以� 異⑸룎濡� �명븳 李멸� �ㅽ뙣 (Alice)
+    await expect(
+      MeetingService.joinMeeting(meeting.meeting_id, aliceId)
+    ).rejects.toThrow('�ㅼ�以꾩씠 寃뱀묩�덈떎');
+
+    // 3-3. Charlie 李멸� �깃났
+    await MeetingService.joinMeeting(meeting.meeting_id, charlieId);
+    const charlieSchedules = await Schedule.findAll({
+      where: {
+        user_id: charlieId,
+        title: `踰덇컻 紐⑥엫: ${meetingData.title}`
+      }
+    });
+    expect(charlieSchedules.length).toBe(3);
+
+    // 3-4. Charlie�� 誘명똿 紐⑸줉 議고쉶
+    const charlieMyMeetings = await MeetingService.getMyMeetings(charlieId, pagination);
+    expect(charlieMyMeetings.content.length).toBe(1);
+    expect(charlieMyMeetings.content[0].isParticipant).toBe(true);
+    expect(charlieMyMeetings.content[0].title).toBe('�ㅽ꽣�� 紐⑥엫');
+
+    // 3-5. Charlie 誘명똿 �덊눜
+    await MeetingService.leaveMeeting(meeting.meeting_id, charlieId);
+
+    // �덊눜 �� �ㅼ�以� ��젣 �뺤씤
+    const remainingCharlieSchedules = await Schedule.findAll({
+      where: {
+        user_id: charlieId,
+        title: `踰덇컻 紐⑥엫: ${meetingData.title}`
+      }
+    });
+    expect(remainingCharlieSchedules.length).toBe(0);
+
+    // �덊눜 �� 誘명똿 紐⑸줉 �뺤씤
+    const charlieMyMeetingsAfterLeave = await MeetingService.getMyMeetings(charlieId, pagination);
+    expect(charlieMyMeetingsAfterLeave.content.length).toBe(0);
+
+    // 3-6. �앹꽦�� �덊눜 �쒕룄 (�ㅽ뙣)
+    await expect(
+      MeetingService.leaveMeeting(meeting.meeting_id, bobId)
+    ).rejects.toThrow('紐⑥엫 �앹꽦�먮뒗 �덊눜�� �� �놁뒿�덈떎');
+
+    // 3-7. 誘명똿 留덇컧
+    await MeetingService.closeMeeting(meeting.meeting_id);
+    const closedMeeting = await Meeting.findByPk(meeting.meeting_id);
+    expect(closedMeeting.type).toBe('CLOSE');
+
+    // 3-8. 留덇컧�� 誘명똿 李멸� �쒕룄 (�ㅽ뙣)
+    await expect(
+      MeetingService.joinMeeting(meeting.meeting_id, charlieId)
+    ).rejects.toThrow('�대� 留덇컧�� 紐⑥엫�낅땲��');
+
+    /**
+     * 4. 誘명똿 議고쉶 �쒕굹由ъ삤
+     * �꾩껜 誘명똿 紐⑸줉 議고쉶
+     * 李몄뿬�섍퀬 �덈뒗 誘명똿 紐⑸줉 議고쉶
+     * �곸꽭 �뺣낫 議고쉶
+     */
+    console.time('Meeting Queries');
+
+    // 4-1. �꾩껜 誘명똿 紐⑸줉 議고쉶
+    const allMeetings = await MeetingService.getMeetings(aliceId, pagination);
+    expect(allMeetings.content.length).toBe(1);
+    expect(allMeetings.content[0].isScheduleConflict).toBe(true);
+
+    // 4-2. Bob�� 誘명똿 紐⑸줉 議고쉶 (�앹꽦��)
+    const bobMyMeetings = await MeetingService.getMyMeetings(bobId, pagination);
+    expect(bobMyMeetings.content.length).toBe(1);
+    expect(bobMyMeetings.content[0].isParticipant).toBe(true);
+    expect(bobMyMeetings.content[0].creatorName).toBe('Bob');
+
+    // 4-2. Alice�� 誘명똿 紐⑸줉 議고쉶 (李몄뿬 x, �앹꽦 x)
+    const aliceMyMeetings = await MeetingService.getMyMeetings(aliceId, pagination);
+    expect(aliceMyMeetings.content.length).toBe(0);
+    // expect(aliceMyMeetings.content[0].isParticipant).toBe(true);
+    // expect(aliceMyMeetings.content[0].creatorName).toBe('Bob');
+
+    // 4-3. �곸꽭 �뺣낫 議고쉶
+    const meetingDetail = await MeetingService.getMeetingDetail(meeting.meeting_id, aliceId);
+    expect(meetingDetail.isScheduleConflict).toBe(true);
+    expect(meetingDetail.creatorName).toBe('Bob');
+    expect(meetingDetail.participants).toBeDefined();
+
+    console.timeEnd('Meeting Queries');
+
+  }, 10000);
+});
-- 
GitLab


From fbd8ba427f8a4731bc2a376563b53a8a67fac2e0 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: Tue, 26 Nov 2024 16:43:45 +0900
Subject: [PATCH 12/14] =?UTF-8?q?refactor:=20=EB=AF=B8=ED=8C=85=20?=
 =?UTF-8?q?=EC=83=9D=EC=84=B1=EC=9E=90=EC=9D=98=20=EC=8A=A4=EC=BC=80?=
 =?UTF-8?q?=EC=A4=84=20=ED=99=95=EC=9D=B8=20=EB=A1=9C=EC=A7=81=20=EC=B6=94?=
 =?UTF-8?q?=EA=B0=80=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/meetingService.js | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/services/meetingService.js b/services/meetingService.js
index 5cfe533..0742e55 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -62,6 +62,15 @@ class MeetingService {
             throw new Error('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ �쒓컙�� �좏깮�댁<�몄슂.');
         }
 
+        const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
+            created_by,
+            time_idx_start,
+            time_idx_end
+        );
+        if (hasConflict) {
+            throw new Error('�대떦 �쒓컙�� �대� �ㅻⅨ �ㅼ�以꾩씠 �덉뒿�덈떎.');
+        }
+
         // �몃옖��뀡�� �ъ슜�섏뿬 紐⑥엫 �앹꽦怨� �ㅼ�以� 異붽�瑜� �먯옄�곸쑝濡� 泥섎━
         return await Meeting.sequelize.transaction(async (transaction) => {
             const chatRoomData = this._constructChatRoomData(title, user, userFcmTokens);
-- 
GitLab


From aebab4f58f84b60fe9c3448645b7000499552d6a 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: Tue, 26 Nov 2024 16:44:01 +0900
Subject: [PATCH 13/14] =?UTF-8?q?test:=20=EB=AF=B8=ED=8C=85=20=EC=83=9D?=
 =?UTF-8?q?=EC=84=B1=EC=9E=90=EC=9D=98=20=EC=8A=A4=EC=BC=80=EC=A4=84=20con?=
 =?UTF-8?q?flict=20=ED=99=95=EC=9D=B8=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20(#19?=
 =?UTF-8?q?)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 services/integration.test.js | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/services/integration.test.js b/services/integration.test.js
index 6375ce7..f004ce1 100644
--- a/services/integration.test.js
+++ b/services/integration.test.js
@@ -152,6 +152,20 @@ describe('System Integration Test', () => {
     console.time('Meeting Operations');
 
     // 3-1. 誘명똿 �앹꽦 諛� �ㅼ�以� �먮룞 �깅줉
+    const aliceConflictMeeting = {
+      title: '�ㅽ꽣�� 紐⑥엫',
+      time_idx_start: 36,
+      time_idx_end: 38,
+      created_by: aliceId,
+      type: 'OPEN',
+      time_idx_deadline: 35,
+      location: 'Room A'
+    };
+
+    await expect(
+      MeetingService.createMeeting(aliceConflictMeeting)
+    ).rejects.toThrow('�대떦 �쒓컙�� �대� �ㅻⅨ �ㅼ�以꾩씠 �덉뒿�덈떎');
+
     const meetingData = {
       title: '�ㅽ꽣�� 紐⑥엫',
       time_idx_start: 36,
-- 
GitLab


From 5fe4877b1832c1ce703c86c1f4956f8185e4dd67 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: Tue, 26 Nov 2024 20:53:08 +0900
Subject: [PATCH 14/14] =?UTF-8?q?fix:=20=EC=A4=91=EB=B3=B5=EB=90=98?=
 =?UTF-8?q?=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=A3=BC=EC=84=9D=20=EC=B2=98?=
 =?UTF-8?q?=EB=A6=AC=20(#19)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 models/index.js            |  2 --
 services/meetingService.js | 24 ++++++++++++------------
 2 files changed, 12 insertions(+), 14 deletions(-)

diff --git a/models/index.js b/models/index.js
index 9ad167a..94c499b 100644
--- a/models/index.js
+++ b/models/index.js
@@ -2,10 +2,8 @@
 
 const sequelize = require('../config/sequelize');
 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');
diff --git a/services/meetingService.js b/services/meetingService.js
index 0742e55..f3d5e92 100644
--- a/services/meetingService.js
+++ b/services/meetingService.js
@@ -1,7 +1,7 @@
 
-const { Meeting, MeetingParticipant, User, Schedule } = require('../models');
-const ChatRoom = require('../models/chatRooms');
-const FcmToken = require('../models/fcmToken');
+// const { Meeting, MeetingParticipant, User, Schedule } = require('../models');
+// const ChatRoom = require('../models/chatRooms');
+// const FcmToken = require('../models/fcmToken');
 // services/meetingService.js
 const { v4: uuidv4 } = require('uuid');
 const { Op } = require('sequelize');
@@ -52,15 +52,15 @@ class MeetingService {
         const userFcmTokens = user.fcmTokenList.map((fcmToken) => fcmToken.token);
 
         // �ㅼ�以� 異⑸룎 �뺤씤
-        const hasConflict = await ScheduleService.checkScheduleOverlap(
-            created_by,
-            new Date(start_time),
-            new Date(end_time)
-        );
-
-        if (hasConflict) {
-            throw new Error('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ �쒓컙�� �좏깮�댁<�몄슂.');
-        }
+        // const hasConflict = await ScheduleService.checkScheduleOverlap(
+        //     created_by,
+        //     new Date(start_time),
+        //     new Date(end_time)
+        // );
+
+        // if (hasConflict) {
+        //     throw new Error('�ㅼ�以꾩씠 寃뱀묩�덈떎. �ㅻⅨ �쒓컙�� �좏깮�댁<�몄슂.');
+        // }
 
         const hasConflict = await ScheduleService.checkScheduleOverlapByTime(
             created_by,
-- 
GitLab