From bb795578766bda5a043b10bc6a374318ee9e1107 Mon Sep 17 00:00:00 2001 From: geonhee-min Date: Wed, 10 Dec 2025 17:14:09 +0900 Subject: [PATCH] =?UTF-8?q?issue=20#65=20-=20=EC=9D=BC=EC=A0=95=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20=EA=B8=B0=EB=8A=A5=201=EC=B0=A8=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../schedule/dto/create/create-request.dto.ts | 13 +-- .../dto/create/create-response.dto.ts | 3 + src/modules/schedule/dto/index.ts | 7 ++ src/modules/schedule/schedule.controller.ts | 27 +++++ src/modules/schedule/schedule.module.ts | 13 +++ src/modules/schedule/schedule.repo.ts | 98 +++++++++++++++---- src/modules/schedule/schedule.service.ts | 69 +++++++++++++ src/util/converter.ts | 9 ++ 8 files changed, 210 insertions(+), 29 deletions(-) create mode 100644 src/modules/schedule/dto/index.ts diff --git a/src/modules/schedule/dto/create/create-request.dto.ts b/src/modules/schedule/dto/create/create-request.dto.ts index ef39092..be67704 100644 --- a/src/modules/schedule/dto/create/create-request.dto.ts +++ b/src/modules/schedule/dto/create/create-request.dto.ts @@ -1,17 +1,14 @@ -import { IsArray, IsDate, IsString } from '@nestjs/class-validator'; +import { IsArray, IsDateString, IsString } from '@nestjs/class-validator'; export class CreateRequestDto { @IsString() name: string; - @IsDate() - startDate: Date; + @IsDateString() + startDate: string; - @IsDate() - endDate: Date; - - @IsString() - status: string; + @IsDateString() + endDate: string; @IsString() content: string; diff --git a/src/modules/schedule/dto/create/create-response.dto.ts b/src/modules/schedule/dto/create/create-response.dto.ts index e69de29..6f7e720 100644 --- a/src/modules/schedule/dto/create/create-response.dto.ts +++ b/src/modules/schedule/dto/create/create-response.dto.ts @@ -0,0 +1,3 @@ +import { BaseResponseDto } from "src/common/dto/base-response.dto"; + +export class CreateResponseDto extends BaseResponseDto {} \ No newline at end of file diff --git a/src/modules/schedule/dto/index.ts b/src/modules/schedule/dto/index.ts new file mode 100644 index 0000000..a8a84a1 --- /dev/null +++ b/src/modules/schedule/dto/index.ts @@ -0,0 +1,7 @@ +export { CreateRequestDto as CreateRequest } from './create/create-request.dto'; +export { CreateResponseDto as CreateResponse } from './create/create-response.dto' + +export { ListRequestDto as ListRequest } from './list/list-request.dto'; +export { ListResponseDto as ListResponse } from './list/list-response.dto'; + +export { DetailResponseDto as DetailResponse } from './detail/detail-response.dto'; \ No newline at end of file diff --git a/src/modules/schedule/schedule.controller.ts b/src/modules/schedule/schedule.controller.ts index e69de29..a55de23 100644 --- a/src/modules/schedule/schedule.controller.ts +++ b/src/modules/schedule/schedule.controller.ts @@ -0,0 +1,27 @@ +import { Body, Controller, Get, Param, Post, Req, UseGuards } from "@nestjs/common"; +import { JwtAccessAuthGuard } from "src/middleware/auth/guard/access-token.guard"; +import { ScheduleService } from "./schedule.service"; +import * as DTO from './dto'; +@UseGuards(JwtAccessAuthGuard) +@Controller('schedule') +export class ScheduleController { + constructor(private readonly scheduleService: ScheduleService) {} + + @Post('/') + async getList(@Req() req, @Body() data: DTO.ListRequest): Promise { + const result = await this.scheduleService.getList(req.user.id, data); + return result; + } + + @Get('/:id') + async getDetail(@Param('id') id: string): Promise { + const result = await this.scheduleService.getDetail(id); + return result; + } + + @Post('/create') + async create(@Req() req, @Body() data: DTO.CreateRequest): Promise { + const result = await this.scheduleService.create(req.user.id, data); + return result; + } +} \ No newline at end of file diff --git a/src/modules/schedule/schedule.module.ts b/src/modules/schedule/schedule.module.ts index e69de29..ce1919f 100644 --- a/src/modules/schedule/schedule.module.ts +++ b/src/modules/schedule/schedule.module.ts @@ -0,0 +1,13 @@ +import { forwardRef, Module } from "@nestjs/common"; +import { AuthModule } from "src/middleware/auth/auth.module"; +import { ScheduleController } from "./schedule.controller"; +import { ScheduleService } from "./schedule.service"; +import { ScheduleRepo } from "./schedule.repo"; + +@Module({ + imports: [forwardRef(() => AuthModule)], + controllers: [ScheduleController], + providers: [ScheduleService, ScheduleRepo], + exports: [ScheduleService, ScheduleRepo] +}) +export class ScheduleModule {} \ No newline at end of file diff --git a/src/modules/schedule/schedule.repo.ts b/src/modules/schedule/schedule.repo.ts index a18e179..b677ecb 100644 --- a/src/modules/schedule/schedule.repo.ts +++ b/src/modules/schedule/schedule.repo.ts @@ -1,43 +1,99 @@ import { Inject, Injectable } from '@nestjs/common'; import * as schema from 'drizzle/schema'; -import { countDistinct, and, eq } from 'drizzle-orm'; +import { countDistinct, and, eq, gt, gte, lte, like, inArray } from 'drizzle-orm'; import { NodePgDatabase } from 'drizzle-orm/node-postgres'; +import * as DTO from './dto'; +import { Converter } from 'src/util/converter'; @Injectable() export class ScheduleRepo { constructor(@Inject('DRIZZLE') private readonly db: NodePgDatabase) {} - async getList(accountId: string) { + async getList(accountId: string, data: DTO.ListRequest) { + const { startDate, endDate, name, status, styleList, typeList } = data; + const schedule = schema.schedule; + + const result = await this + .db + .select({ + id: schedule.id, + name: schedule.name, + startDate: schedule.startDate, + endDate: schedule.endDate, + status: schedule.status, + style: schedule.style, + type: schedule.style, + }) + .from(schedule) + .where( + and( + eq(schedule.owner, accountId), + startDate ? gte(schedule.startDate, Converter.formatDateToSqlDate(startDate)) : undefined, + endDate ? lte(schedule.endDate, Converter.formatDateToSqlDate(endDate)) : undefined, + name ? like(schedule.name, `%${name}%`) : undefined, + (typeList && typeList.length > 0) ? inArray(schedule.type, typeList) : undefined, + (styleList && styleList.length > 0) ? inArray(schedule.style, styleList) : undefined, + status ? eq(schedule.status, status) : undefined, + eq(schedule.isDeleted, false) + ) + ) + + const resultData = result.map((schedule) => { + return { + id: schedule.id, + name: schedule.name, + type: schedule.type, + style: schedule.style, + status: schedule.status, + startDate: new Date(schedule.startDate), + endDate: new Date(schedule.endDate) + } + }) + + return resultData; + } + + async getDetail(id: string) { + const schedule = schema.schedule; const result = await this .db .select() - .from(schema.schedule) + .from(schedule) .where( and( - eq(schema.schedule.owner, accountId), - eq(schema.schedule.isDeleted, false) + eq(schedule.id, id), + eq(schedule.isDeleted, false) ) ); return result; } - async getDetail(id: string) { - const result = await this + async create( + accountId: string, + name: string, + startDate: string, + endDate: string, + startTime: string, + endTime: string, + style: string, + content: string, + type: string + ) { + return await this .db - .select() - .from(schema.schedule) - .where( - and( - eq(schema.schedule.id, id), - eq(schema.schedule.isDeleted, false) - ) - ); - - return result[0]; - } - - async create() { - + .insert(schema.schedule) + .values({ + name: name, + content: content, + owner: accountId, + startDate: startDate, + endDate: endDate, + startTime: startTime, + endTime: endTime, + status: 'yet', + style: style, + type: type + }); } } \ No newline at end of file diff --git a/src/modules/schedule/schedule.service.ts b/src/modules/schedule/schedule.service.ts index e69de29..65a0fb4 100644 --- a/src/modules/schedule/schedule.service.ts +++ b/src/modules/schedule/schedule.service.ts @@ -0,0 +1,69 @@ +import { Injectable } from "@nestjs/common"; +import { ScheduleRepo } from "./schedule.repo"; +import * as DTO from './dto'; + +@Injectable() +export class ScheduleService { + constructor( + private readonly scheduleRepo: ScheduleRepo + ) {} + + async getList(accountId: string, data: DTO.ListRequest): Promise { + const result = await this.scheduleRepo.getList(accountId, data); + + return { + success: true, + data: result + }; + } + + async getDetail(id: string) { + const result = await this.scheduleRepo.getDetail(id); + + if (result.length < 1) { + return { + success: false, + message: '존재하지 않는 일정입니다.' + }; + } + + const data = { + ...result[0], + startDate: new Date(result[0].startDate), + endDate: new Date(result[0].endDate) + } + + return { + success: true, + data: data + }; + } + + async create(accountId: string, data: DTO.CreateRequest): Promise { + const { name, content, startDate, endDate, startTime, endTime, style, type } = data; + + const result = await this.scheduleRepo.create( + accountId, + name, + startDate, + endDate, + startTime, + endTime, + style, + content, + type + ); + + if (result.rowCount) { + return { + success: true, + message: "일정이 생성되었습니다." + }; + } else { + return { + success: false, + message: "일정 생성에 실패하였습니다." + } + } + } +} \ No newline at end of file diff --git a/src/util/converter.ts b/src/util/converter.ts index cc6a246..c3ea70f 100644 --- a/src/util/converter.ts +++ b/src/util/converter.ts @@ -8,4 +8,13 @@ export class Converter { static comparePassword(rawPassword: string, hashedPassword: string) { return bcrypt.compareSync(rawPassword, hashedPassword); } + + static formatDateToSqlDate(date: string): string { + const targetDate = new Date(date); + const year = targetDate.getUTCFullYear(); + const month = (targetDate.getUTCMonth() + 1).toString().padStart(2, '0'); + const day = (targetDate.getUTCDate()).toString().padStart(2, '0'); + + return `${year}-${month}-${day}`; + } } \ No newline at end of file