diff --git a/src/response/dto/check-response.dto.ts b/src/response/dto/check-response.dto.ts index 20c82f6..82d927b 100644 --- a/src/response/dto/check-response.dto.ts +++ b/src/response/dto/check-response.dto.ts @@ -1,9 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { ResponseDto } from '../../responseDto'; -export class Success_CheckDto extends ResponseDto { +export class Success_CheckResponseDto extends ResponseDto { @ApiProperty({ - default: 'Get selected successfully.', + default: '학생이 선생님을 선택했습니다. 과외를 시작하세요.', }) message: string; @@ -19,66 +19,20 @@ export class Success_CheckDto extends ResponseDto { @ApiProperty({ default: { - id: 'test-request-id', - student_id: 'test-student-id', status: 'selected', - tutoring_id: 'test-tutoring-id', + tutoringId: 'test-tutoring-id', }, }) data: object; -} - -export class Not_checkDto extends ResponseDto { - @ApiProperty({ - default: 'Get selected successfully.', - }) - message: string; - - @ApiProperty({ - default: false, - }) - error: boolean; - - @ApiProperty({ - default: 200, - }) - statusCode: number; - - @ApiProperty({ - default: { - status: 'not selected', - }, - }) - data: object; -} - -export class Yet_checkDto extends ResponseDto { - @ApiProperty({ - default: 'Get selected successfully.', - }) - message: string; - @ApiProperty({ - default: false, - }) - error: boolean; - - @ApiProperty({ - default: 200, - }) - statusCode: number; - - @ApiProperty({ - default: { - status: 'pending', - }, - }) - data: object; + constructor(message: string, data: object) { + super(200, message, false, data); + } } -export class NotFound_checkDto extends ResponseDto { +export class NotFound_CheckResponseDto extends ResponseDto { @ApiProperty({ - default: 'Request not found.', + default: '리소스를 찾을 수 없습니다.', }) message: string; @@ -91,4 +45,8 @@ export class NotFound_checkDto extends ResponseDto { default: 404, }) statusCode: number; + + constructor(message: string) { + super(404, message, true); + } } diff --git a/src/response/dto/create-response.dto.ts b/src/response/dto/create-response.dto.ts index 2f05f3c..99c34ae 100644 --- a/src/response/dto/create-response.dto.ts +++ b/src/response/dto/create-response.dto.ts @@ -1,29 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { ResponseDto } from '../../responseDto'; -export class SelectResponseDto { - @ApiProperty({ - description: '요청의 id', - default: 'test-request-id', - }) - requestId: string; - - @ApiProperty({ - description: '학생의 id', - default: 'test-student-id', - }) - studentId: string; - - @ApiProperty({ - description: '선생님의 id', - default: 'test-teacher-id', - }) - teacherId: string; -} - -export class NotModified_SelectResponseDto extends ResponseDto { +export class NotFound_SelectResponseDto extends ResponseDto { @ApiProperty({ - default: 'Already selected.', + default: '리소스를 찾을 수 없습니다.', }) message: string; @@ -33,19 +13,18 @@ export class NotModified_SelectResponseDto extends ResponseDto { error: boolean; @ApiProperty({ - default: 304, + default: 404, }) statusCode: number; - @ApiProperty({ - default: null, - }) - data: object; + constructor(message: string) { + super(404, message, true); + } } -export class Success_SelectResponseDto extends ResponseDto { +export class Created_CreateResponseDto extends ResponseDto { @ApiProperty({ - default: 'Select response successfully.', + default: '응답을 성공적으로 추가했습니다.', }) message: string; @@ -59,40 +38,14 @@ export class Success_SelectResponseDto extends ResponseDto { }) statusCode: number; - @ApiProperty({ - default: { - requestId: 'test-request-id', - tutoringId: 'test-tutoring-id', - }, - }) - data: SelectResponseDto; + constructor() { + super(200, '응답을 성공적으로 추가했습니다.', false); + } } -export class BadRequest_SelectResponseDto extends ResponseDto { - @ApiProperty({ - default: 'Request not found.', - }) - message: string; - - @ApiProperty({ - default: true, - }) - error: boolean; - - @ApiProperty({ - default: 400, - }) - statusCode: number; - - @ApiProperty({ - default: null, - }) - data: object; -} - -export class NotFound_SelectResponseDto extends ResponseDto { +export class NotFound_CreateResponseDto extends ResponseDto { @ApiProperty({ - default: 'Teacher not found.', + default: '리소스를 찾을 수 없습니다.', }) message: string; @@ -106,39 +59,14 @@ export class NotFound_SelectResponseDto extends ResponseDto { }) statusCode: number; - @ApiProperty({ - default: null, - }) - data: object; -} - -export class Created_CreateResponseDto extends ResponseDto { - @ApiProperty({ - default: 'Append response successfully.', - }) - message: string; - - @ApiProperty({ - default: false, - }) - error: boolean; - - @ApiProperty({ - default: 200, - }) - statusCode: number; - - @ApiProperty({ - default: { - id: 'test-request-id', - }, - }) - data: object; + constructor(message: string) { + super(404, message, true); + } } -export class NotFound_CreateResponseDto extends ResponseDto { +export class Conflict_CreateResponseDto extends ResponseDto { @ApiProperty({ - default: 'Request not found.', + default: '이미 답변이 존재합니다.', }) message: string; @@ -148,12 +76,11 @@ export class NotFound_CreateResponseDto extends ResponseDto { error: boolean; @ApiProperty({ - default: 404, + default: 409, }) statusCode: number; - @ApiProperty({ - default: null, - }) - data: object; + constructor(message: string) { + super(409, message, true); + } } diff --git a/src/response/dto/delete-response.dto.ts b/src/response/dto/delete-response.dto.ts index aa2fa1a..b4d9400 100644 --- a/src/response/dto/delete-response.dto.ts +++ b/src/response/dto/delete-response.dto.ts @@ -3,7 +3,7 @@ import { ResponseDto } from '../../responseDto'; export class Success_DeleteResponseDto extends ResponseDto { @ApiProperty({ - default: 'Append response successfully.', + default: '응답을 성공적으로 삭제했습니다.', }) message: string; @@ -17,17 +17,14 @@ export class Success_DeleteResponseDto extends ResponseDto { }) statusCode: number; - @ApiProperty({ - default: { - id: 'test-request-id', - }, - }) - data: object; + constructor() { + super(200, '응답을 성공적으로 삭제했습니다.', false); + } } export class NotFound_DeleteResponseDto extends ResponseDto { @ApiProperty({ - default: 'Request not found.', + default: '리소스를 찾을 수 없습니다.', }) message: string; @@ -41,8 +38,7 @@ export class NotFound_DeleteResponseDto extends ResponseDto { }) statusCode: number; - @ApiProperty({ - default: null, - }) - data: object; + constructor(message: string) { + super(404, message, true); + } } diff --git a/src/response/dto/get-response.dto.ts b/src/response/dto/get-response.dto.ts index 9de3a7d..c3860c0 100644 --- a/src/response/dto/get-response.dto.ts +++ b/src/response/dto/get-response.dto.ts @@ -4,7 +4,7 @@ import { ResponseDto } from '../../responseDto'; export class Success_GetTeachersDTO extends ResponseDto { @ApiProperty({ - default: 'Get teachers successfully.', + default: '응답한 선생님 목록을 성공적으로 가져왔습니다.', }) message: string; @@ -31,11 +31,15 @@ export class Success_GetTeachersDTO extends ResponseDto { ], }) data: User[]; + + constructor(data: User[]) { + super(200, '응답한 선생님 목록을 성공적으로 가져왔습니다.', false, data); + } } export class NotFound_GetTeachersDTO extends ResponseDto { @ApiProperty({ - default: 'Request not found.', + default: '과외 요청을 찾을 수 없습니다.', }) message: string; @@ -48,4 +52,8 @@ export class NotFound_GetTeachersDTO extends ResponseDto { default: 404, }) statusCode: number; + + constructor() { + super(404, '과외 요청을 찾을 수 없습니다.', true); + } } diff --git a/src/response/dto/select-response.dto.ts b/src/response/dto/select-response.dto.ts new file mode 100644 index 0000000..ca08ec6 --- /dev/null +++ b/src/response/dto/select-response.dto.ts @@ -0,0 +1,93 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { ResponseDto } from '../../responseDto'; + +export class SelectResponseDto { + @ApiProperty({ + description: '요청의 id', + default: 'test-request-id', + }) + requestId: string; + + @ApiProperty({ + description: '학생의 id', + default: 'test-student-id', + }) + studentId: string; + + @ApiProperty({ + description: '선생님의 id', + default: 'test-teacher-id', + }) + teacherId: string; +} + +export class Success_SelectResponseDto extends ResponseDto { + @ApiProperty({ + default: '선생님을 선택했습니다.', + }) + message: string; + + @ApiProperty({ + default: false, + }) + error: boolean; + + @ApiProperty({ + default: 200, + }) + statusCode: number; + + @ApiProperty({ + default: { + tutoringId: 'test-tutoring-id', + }, + }) + data: object; + + constructor(data: object) { + super(200, '선생님을 선택했습니다.', false, data); + } +} + +export class Conflict_SelectResponseDto extends ResponseDto { + @ApiProperty({ + default: '이미 선생님을 선택했습니다.', + }) + message: string; + + @ApiProperty({ + default: true, + }) + error: boolean; + + @ApiProperty({ + default: 304, + }) + statusCode: number; + + constructor() { + super(304, '이미 선생님을 선택했습니다.', true); + } +} + +export class BadRequest_SelectResponseDto extends ResponseDto { + @ApiProperty({ + default: 'Request not found.', + }) + message: string; + + @ApiProperty({ + default: true, + }) + error: boolean; + + @ApiProperty({ + default: 400, + }) + statusCode: number; + + @ApiProperty({ + default: null, + }) + data: object; +} diff --git a/src/response/response.controller.ts b/src/response/response.controller.ts index f3c17c5..a30f3be 100644 --- a/src/response/response.controller.ts +++ b/src/response/response.controller.ts @@ -12,37 +12,73 @@ import { Success_GetTeachersDTO, } from './dto/get-response.dto'; import { - Not_checkDto, - NotFound_checkDto, - Success_CheckDto, - Yet_checkDto, + NotFound_CheckResponseDto, + Success_CheckResponseDto, } from './dto/check-response.dto'; import { - BadRequest_SelectResponseDto, Created_CreateResponseDto, NotFound_CreateResponseDto, NotFound_SelectResponseDto, - NotModified_SelectResponseDto, - SelectResponseDto, - Success_SelectResponseDto, } from './dto/create-response.dto'; import { NotFound_DeleteResponseDto, Success_DeleteResponseDto, } from './dto/delete-response.dto'; +import { + BadRequest_SelectResponseDto, + Conflict_SelectResponseDto, + SelectResponseDto, + Success_SelectResponseDto, +} from './dto/select-response.dto'; @ApiTags('Response') @Controller('response') export class ResponseController { constructor(private readonly responseService: ResponseService) {} - @Get('teacherList/:id') + @Post('create/:requestId') + @ApiOperation({ + summary: '특정 요청에 대한 선생님의 응답 생성 (대기열 참가)', + description: '`TEACHER`\n\n특정 요청 대기열에 자신을 추가합니다.', + }) + @ApiParam({ + name: 'requestId', + description: '요청의 id', + example: 'test-request-id', + }) + @ApiBody({ + description: '선생님의 id', + schema: { + type: 'string', + example: { + teacherId: 'test-teacher-id', + }, + }, + }) + @ApiResponse({ + status: 200, + description: '해당 요청에 대한 응답을 성공적으로 생성했습니다.', + type: Created_CreateResponseDto, + }) + @ApiResponse({ + status: 404, + description: '해당 요청이 존재하지 않습니다.', + type: NotFound_CreateResponseDto, + }) + create( + @Param('requestId') requestId: string, + @Body('teacherId') teacherId: string, + ) { + return this.responseService.create(requestId, teacherId); + } + + @Get('teacherList/:requestId') @ApiOperation({ summary: '특정 요청에 대한 선생님들의 목록 조회', description: '`STUDENT`\n\n특정 요청에 대한 선생님들의 목록을 조회합니다.', }) @ApiParam({ - name: 'id', + name: 'requestId', description: '요청의 id', }) @ApiResponse({ @@ -55,103 +91,95 @@ export class ResponseController { description: '해당 과외 요청이 존재하지 않습니다.', type: NotFound_GetTeachersDTO, }) - findOne(@Param('id') id: string) { - return this.responseService.findOne(id); + getTeachers(@Param('requestId') requestId: string) { + return this.responseService.getTeachers(requestId); } - @Post('check/:id') + @Post('select') @ApiOperation({ - summary: '특정 요청에 대한 선택 여부 조회', - description: '`TEACHER`\n\n특정 요청에 대한 선택 여부를 조회합니다.', - }) - @ApiParam({ - name: 'id', - description: '요청의 id', - example: 'test-request-id', + summary: '특정 과외 응답 선택', + description: '`STUDENT`\n\n특정 과외 응답을 선택합니다.', }) @ApiBody({ - schema: { - type: 'object', - properties: { - teacher_id: { - type: 'string', - description: '선생님의 id', - example: 'test-teacher-id', - }, - }, - }, + type: SelectResponseDto, }) @ApiResponse({ status: 200, - description: '해당 선생님이 선택되었습니다.', - type: Success_CheckDto, + description: '요청이 성공적으로 처리되었습니다.', + type: Success_SelectResponseDto, }) @ApiResponse({ - status: 200, - description: '해당 선생님이 선택되지 않았습니다.', - type: Not_checkDto, + status: 304, + description: '이미 선택된 선생님입니다.', + type: Conflict_SelectResponseDto, }) @ApiResponse({ - status: 200, - description: '학생의 선택을 기다리고 있습니다.', - type: Yet_checkDto, + status: 400, + description: '해당 요청이 존재하지 않습니다.', + type: BadRequest_SelectResponseDto, }) @ApiResponse({ status: 404, - description: '해당 요청이 존재하지 않습니다.', - type: NotFound_checkDto, + description: '해당 선생님이 존재하지 않습니다.', + type: NotFound_SelectResponseDto, }) - check(@Param('id') id: string, @Body('teacher_id') teacher_id: string) { - return this.responseService.check(id, teacher_id); + select(@Body() selectResponseDto: SelectResponseDto) { + return this.responseService.select(selectResponseDto); } - @Post('create/:id') + @Post('check/:requestId') @ApiOperation({ - summary: '특정 요청에 대한 선생님의 응답 생성 (대기열 참가)', - description: '`TEACHER`\n\n특정 요청 대기열에 자신을 추가합니다.', + summary: '특정 요청에 대한 선택 여부 조회', + description: '`TEACHER`\n\n특정 요청에 대한 선택 여부를 조회합니다.', }) @ApiParam({ - name: 'id', + name: 'requestId', description: '요청의 id', example: 'test-request-id', }) @ApiBody({ - description: '선생님의 id', schema: { - type: 'string', - example: { - teacher_id: 'test-teacher-id', + type: 'object', + properties: { + teacherId: { + type: 'string', + description: '선생님의 id', + example: 'test-teacher-id', + }, }, }, }) @ApiResponse({ status: 200, - description: '해당 요청에 대한 응답을 성공적으로 생성했습니다.', - type: Created_CreateResponseDto, + description: '선택 여부를 성공적으로 조회했습니다.', + type: Success_CheckResponseDto, }) @ApiResponse({ status: 404, - description: '해당 요청이 존재하지 않습니다.', - type: NotFound_CreateResponseDto, - }) - update(@Param('id') id: string, @Body('teacher_id') teacher_id: string) { - return this.responseService.update(id, teacher_id); + description: '리소스를 찾을 수 없습니다.', + type: NotFound_CheckResponseDto, + }) + check( + @Param('requestId') requestId: string, + @Body('teacherId') teacherId: string, + ) { + return this.responseService.check(requestId, teacherId); } - @Delete(':id') + @Delete('delete/:requestId') @ApiOperation({ summary: '특정 응답 삭제', description: '`TEACHER`\n\n특정 응답을 삭제합니다.', }) @ApiParam({ - name: 'id', + name: 'requestId', description: '요청 id', }) @ApiBody({ schema: { type: 'string', example: { - teacher_id: '선생님의 id', + teacherId: '선생님의 id', }, }, }) @@ -165,39 +193,10 @@ export class ResponseController { description: '해당 요청이 존재하지 않습니다.', type: NotFound_DeleteResponseDto, }) - remove(@Param('id') id: string, @Body('teacher_id') teacher_id: string) { - return this.responseService.remove(id, teacher_id); - } - - @Post('select') - @ApiOperation({ - summary: '특정 과외 응답 선택', - description: '`STUDENT`\n\n특정 과외 응답을 선택합니다.', - }) - @ApiBody({ - type: SelectResponseDto, - }) - @ApiResponse({ - status: 200, - description: '요청이 성공적으로 처리되었습니다.', - type: Success_SelectResponseDto, - }) - @ApiResponse({ - status: 304, - description: '이미 선택된 선생님입니다.', - type: NotModified_SelectResponseDto, - }) - @ApiResponse({ - status: 400, - description: '해당 요청이 존재하지 않습니다.', - type: BadRequest_SelectResponseDto, - }) - @ApiResponse({ - status: 404, - description: '해당 선생님이 존재하지 않습니다.', - type: NotFound_SelectResponseDto, - }) - select(@Body() selectResponseDto: SelectResponseDto) { - return this.responseService.select(selectResponseDto); + delete( + @Param('requestId') requestId: string, + @Body('teacherId') teacherId: string, + ) { + return this.responseService.delete(requestId, teacherId); } } diff --git a/src/response/response.service.ts b/src/response/response.service.ts index fd0d441..6ad43c8 100644 --- a/src/response/response.service.ts +++ b/src/response/response.service.ts @@ -1,10 +1,32 @@ -import { HttpException, Injectable } from '@nestjs/common'; +import { Injectable } from '@nestjs/common'; import { InjectModel, Model } from 'nestjs-dynamoose'; import { User, UserKey } from '../user/entities/user.interface'; import { Request, RequestKey } from '../request/entities/request.interface'; import { Tutoring, TutoringKey } from '../tutoring/entities/tutoring.interface'; -import { SelectResponseDto } from './dto/create-response.dto'; +import { + Conflict_CreateResponseDto, + Created_CreateResponseDto, + NotFound_CreateResponseDto, + NotFound_SelectResponseDto, +} from './dto/create-response.dto'; +import { + Conflict_SelectResponseDto, + SelectResponseDto, + Success_SelectResponseDto, +} from './dto/select-response.dto'; +import { + NotFound_GetTeachersDTO, + Success_GetTeachersDTO, +} from './dto/get-response.dto'; +import { + NotFound_DeleteResponseDto, + Success_DeleteResponseDto, +} from './dto/delete-response.dto'; import { TutoringService } from '../tutoring/tutoring.service'; +import { + NotFound_CheckResponseDto, + Success_CheckResponseDto, +} from './dto/check-response.dto'; @Injectable() export class ResponseService { @@ -17,87 +39,111 @@ export class ResponseService { private tutoringModel: Model, ) {} - async findOne(id: string) { - const request = await this.requestModel.get({ id }); + async create(requestId: string, teacherId: string) { + const request = await this.requestModel.get({ id: requestId }); + if (request === undefined) { + return new NotFound_CreateResponseDto('과외 요청을 찾을 수 없습니다.'); + } + + const teacher = await this.userModel.get({ id: teacherId }); + if (teacher === undefined) { + return new NotFound_CreateResponseDto('선생님을 찾을 수 없습니다.'); + } + + if (request.teacherIds.includes(teacherId)) { + return new Conflict_CreateResponseDto('이미 응답한 선생님입니다.'); + } + + request.teacherIds.push(teacherId); + await this.requestModel.update(request); + + return new Created_CreateResponseDto(); + } + + async getTeachers(requestId: string) { + const request = await this.requestModel.get({ id: requestId }); + if (request === undefined) { + return new NotFound_GetTeachersDTO(); + } + const teachers = []; for (const teacherId of request.teacherIds) { teachers.push(await this.userModel.get({ id: teacherId })); } - return teachers; - } - async update(id: string, teacherId: string) { - await this.requestModel.get({ id }).then(async (response) => { - if (response.teacherIds.includes(teacherId)) { - throw new HttpException('Already selected', 304); - } else { - response.teacherIds.push(teacherId); - await this.requestModel.update(response); - } - }); - return await this.requestModel.get({ id }); + return new Success_GetTeachersDTO(teachers); } - async remove(id: string, teacherId: string) { - return await this.requestModel.get({ id }).then((response) => { - response.teacherIds = response.teacherIds.filter( - (id) => id !== teacherId, + async delete(requestId: string, teacherId: string) { + const request = await this.requestModel.get({ id: requestId }); + if (request === undefined) { + return new NotFound_DeleteResponseDto('과외 요청을 찾을 수 없습니다.'); + } + + if (!request.teacherIds.includes(teacherId)) { + return new NotFound_DeleteResponseDto( + '해당 요청에서 선생님을 찾을 수 없습니다.', ); - this.requestModel.update(response); - }); + } + + request.teacherIds = request.teacherIds.filter((id) => id !== teacherId); + await this.requestModel.update(request); + + return new Success_DeleteResponseDto(); } async select(selectResponseDto: SelectResponseDto) { - let tutoring; - await this.requestModel - .get({ id: selectResponseDto.requestId }) - .then(async (response) => { - response.teacherIds = response.teacherIds.filter( - (id) => id === selectResponseDto.teacherId, - ); - - const tutoringService = new TutoringService(this.tutoringModel); - tutoring = await tutoringService.create(selectResponseDto); - - response.status = 'selected'; - response.tutoringId = tutoring.id; - await this.requestModel.update(response); - }); + const request = await this.requestModel.get({ + id: selectResponseDto.requestId, + }); + if (request === undefined) { + return new NotFound_SelectResponseDto('과외 요청을 찾을 수 없습니다.'); + } - return { - message: 'Selected', - error: false, - data: { - tutoring, - }, - }; + if (request.status === 'selected') { + return new Conflict_SelectResponseDto(); + } + + const tutoringService = new TutoringService(this.tutoringModel); + const tutoring = await tutoringService.create(selectResponseDto); + request.status = 'selected'; + request.selectedTeacherId = selectResponseDto.teacherId; + request.tutoringId = tutoring.id; + await this.requestModel.update(request); + + return new Success_SelectResponseDto({ tutoringId: tutoring.id }); } - async check(id: string, teacherId: string) { - let request; - try { - request = await this.requestModel.get({ id }); - } catch (e) { - throw new HttpException('Not found', 404); + async check(requestId: string, teacherId: string) { + const request = await this.requestModel.get({ id: requestId }); + if (request === undefined) { + return new NotFound_CheckResponseDto('과외 요청을 찾을 수 없습니다.'); } + if (request.status === 'pending') { - throw new HttpException('Yet selected', 200); - } else if (request.status === 'selected') { - const tutoring = await this.tutoringModel.get({ - id: request.tutoringId, + return new Success_CheckResponseDto('학생의 선택을 기다리는 중입니다.', { + status: 'yet selected', }); + } + + if (teacherId !== request.selectedTeacherId) { + return new Success_CheckResponseDto( + '학생이 다른 선생님과 과외를 시작하였습니다.', + { status: 'not selected' }, + ); + } - if (tutoring.teacherId !== teacherId) { - throw new HttpException('Not selected', 200); - } - - return { - message: 'Selected', - error: false, - data: { - tutoring, - }, - }; + const tutoring = await this.tutoringModel.get({ id: request.tutoringId }); + if (tutoring === undefined) { + return new NotFound_CheckResponseDto('과외를 찾을 수 없습니다.'); } + + return new Success_CheckResponseDto( + '학생이 선생님을 선택했습니다. 과외를 시작하세요.', + { + status: request.status, + tutoringId: tutoring.id, + }, + ); } }