From b51c4239d5baf4e5fe5fd0a3f340f93a2647c897 Mon Sep 17 00:00:00 2001 From: Chun Hyunwoo <1000chw@gmail.com> Date: Wed, 10 Jan 2024 18:11:58 +0900 Subject: [PATCH 1/2] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=ED=95=98?= =?UTF-8?q?=EA=B8=B0=20api=20request,=20response,=20converter,=20controlle?= =?UTF-8?q?r=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/user/dto/reqeust/question-request.dto.ts | 18 ++++++++++++++++++ src/user/dto/response/question-response.dto.ts | 6 ++++++ src/user/user.controller.ts | 14 ++++++++++++++ src/user/user.converter.ts | 5 +++++ 4 files changed, 43 insertions(+) create mode 100644 src/user/dto/reqeust/question-request.dto.ts create mode 100644 src/user/dto/response/question-response.dto.ts diff --git a/src/user/dto/reqeust/question-request.dto.ts b/src/user/dto/reqeust/question-request.dto.ts new file mode 100644 index 0000000..a9403bd --- /dev/null +++ b/src/user/dto/reqeust/question-request.dto.ts @@ -0,0 +1,18 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { IsNotEmpty, IsString } from 'class-validator'; + +export class QuestionRequest { + @ApiProperty({ description: '문의 제목' }) + @IsString() + @IsNotEmpty({ message: '제목은 필수입니다.' }) + readonly title: string; + + @ApiProperty({ description: '답변 받을 이메일' }) + @IsString() + @IsNotEmpty({ message: '이메일은 필수입니다.' }) + readonly email: string; + + @ApiProperty({ description: '문의 내용' }) + @IsString() + readonly content: string; +} diff --git a/src/user/dto/response/question-response.dto.ts b/src/user/dto/response/question-response.dto.ts new file mode 100644 index 0000000..48fee16 --- /dev/null +++ b/src/user/dto/response/question-response.dto.ts @@ -0,0 +1,6 @@ +import { ApiProperty } from '@nestjs/swagger'; + +export class QuestionResponse { + @ApiProperty({ description: '문의 전송 여부', example: true }) + isSended: boolean; +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 8c56937..2243531 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -32,6 +32,8 @@ import { ReportUserResponse } from './dto/response/report-user-response.dto'; import { SignUpResponse } from './dto/response/sign-up-response.dto'; import { UserConverter } from './user.converter'; import { UserService } from './user.service'; +import { QuestionResponse } from './dto/response/question-response.dto'; +import { QuestionRequest } from './dto/reqeust/question-request.dto'; @Controller('api/users') @ApiTags('users') @@ -105,4 +107,16 @@ export class UserController { GlobalResponseCode.OK, ); } + + @Post('question') + @UseGuards(JwtAuthGuard) + @ApiOperation({ + summary: '문의 API', + }) + @ApiBearerAuth() + @ApiCreatedResponse({ type: QuestionResponse, description: '문의 전송 성공' }) + async question(@Body() request: QuestionRequest): Promise> { + const isQuestionSended = await this.userService.question(request); + return BaseResponse.of(UserConverter.toQuestionResponse(isQuestionSended)); + } } diff --git a/src/user/user.converter.ts b/src/user/user.converter.ts index d9e6885..cc94d22 100644 --- a/src/user/user.converter.ts +++ b/src/user/user.converter.ts @@ -10,6 +10,7 @@ import { Password } from './entity/password'; import { UserReport } from './entity/user-report.entity'; import { User } from './entity/user.entity'; import { UserReportReason } from './enum/user-report-reason'; +import { QuestionResponse } from './dto/response/question-response.dto'; @Injectable() export class UserConverter implements OnModuleInit { @@ -57,4 +58,8 @@ export class UserConverter implements OnModuleInit { public static toFindingPasswordResponse(isPasswordSended: boolean): FindingPasswordResponse { return Builder(FindingPasswordResponse).isPasswordSended(isPasswordSended).build(); } + + public static toQuestionResponse(isQuestionSended: boolean): QuestionResponse { + return Builder(QuestionResponse).isSended(isQuestionSended).build(); + } } From c6ad9ffd6b5f8eff97f8acc13e5fdbdf0440a93f Mon Sep 17 00:00:00 2001 From: Chun Hyunwoo <1000chw@gmail.com> Date: Wed, 10 Jan 2024 18:32:11 +0900 Subject: [PATCH 2/2] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=20sevice=20?= =?UTF-8?q?=EB=A7=8C=EB=93=A4=EA=B8=B0=20update:=20converter=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20feat:=20question=20entity=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/user/dto/reqeust/question-request.dto.ts | 6 ++++-- src/user/entity/question.entity.ts | 17 +++++++++++++++++ src/user/user.controller.ts | 4 ++-- src/user/user.converter.ts | 7 +++++-- src/user/user.service.ts | 8 ++++++++ 5 files changed, 36 insertions(+), 6 deletions(-) create mode 100644 src/user/entity/question.entity.ts diff --git a/src/user/dto/reqeust/question-request.dto.ts b/src/user/dto/reqeust/question-request.dto.ts index a9403bd..c6c5192 100644 --- a/src/user/dto/reqeust/question-request.dto.ts +++ b/src/user/dto/reqeust/question-request.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsString } from 'class-validator'; +import { IsByteLength, IsNotEmpty, IsString } from 'class-validator'; export class QuestionRequest { @ApiProperty({ description: '문의 제목' }) @@ -14,5 +14,7 @@ export class QuestionRequest { @ApiProperty({ description: '문의 내용' }) @IsString() - readonly content: string; + @IsNotEmpty({ message: '문의 내용은 필수입니다.' }) + @IsByteLength(20, 10000, { message: '문의 내용은 10글자 이상이어야 합니다.' }) + readonly contents: string; } diff --git a/src/user/entity/question.entity.ts b/src/user/entity/question.entity.ts new file mode 100644 index 0000000..4eefc1d --- /dev/null +++ b/src/user/entity/question.entity.ts @@ -0,0 +1,17 @@ +import { BaseEntity } from 'src/global/base/base.entity'; +import { Column, Entity, PrimaryGeneratedColumn } from 'typeorm'; + +@Entity('questions') +export class Question extends BaseEntity { + @PrimaryGeneratedColumn() + questionId: number; + + @Column() + title: string; + + @Column() + reporter: string; + + @Column() + contents: string; +} diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 2243531..244d86e 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -116,7 +116,7 @@ export class UserController { @ApiBearerAuth() @ApiCreatedResponse({ type: QuestionResponse, description: '문의 전송 성공' }) async question(@Body() request: QuestionRequest): Promise> { - const isQuestionSended = await this.userService.question(request); - return BaseResponse.of(UserConverter.toQuestionResponse(isQuestionSended)); + const question = await this.userService.question(request); + return BaseResponse.of(UserConverter.toQuestionResponse(question)); } } diff --git a/src/user/user.converter.ts b/src/user/user.converter.ts index cc94d22..217783e 100644 --- a/src/user/user.converter.ts +++ b/src/user/user.converter.ts @@ -11,6 +11,7 @@ import { UserReport } from './entity/user-report.entity'; import { User } from './entity/user.entity'; import { UserReportReason } from './enum/user-report-reason'; import { QuestionResponse } from './dto/response/question-response.dto'; +import { Question } from './entity/question.entity'; @Injectable() export class UserConverter implements OnModuleInit { @@ -59,7 +60,9 @@ export class UserConverter implements OnModuleInit { return Builder(FindingPasswordResponse).isPasswordSended(isPasswordSended).build(); } - public static toQuestionResponse(isQuestionSended: boolean): QuestionResponse { - return Builder(QuestionResponse).isSended(isQuestionSended).build(); + public static toQuestionResponse(question: Question): QuestionResponse { + return Builder(QuestionResponse) + .isSended(question ? true : false) + .build(); } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 931a8d3..45ce348 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -11,6 +11,8 @@ import { UserReport } from './entity/user-report.entity'; import { User } from './entity/user.entity'; import { UserResponseCode } from './exception/user-response-code'; import { UserConverter } from './user.converter'; +import { QuestionRequest } from './dto/reqeust/question-request.dto'; +import { Question } from './entity/question.entity'; @Injectable() export class UserService { @@ -22,6 +24,8 @@ export class UserService { @InjectRepository(UserReport) private readonly userReportRepository: Repository, private readonly mailService: MailService, + @InjectRepository(Question) + private readonly questionRepository: Repository, ) {} async isUserExists(userId: number): Promise { @@ -87,4 +91,8 @@ export class UserService { async sendEmail(request: FindingPasswordRequest, password: string): Promise { await this.mailService.sendMail(request.email, '[BookJam] 임시 비밀번호 안내', password); } + + async question(request: QuestionRequest) { + return await this.questionRepository.save(request); + } }