diff --git a/src/tutoring/tutoring.repository.ts b/src/tutoring/tutoring.repository.ts index 7a990e7..320a89a 100644 --- a/src/tutoring/tutoring.repository.ts +++ b/src/tutoring/tutoring.repository.ts @@ -173,4 +173,34 @@ export class TutoringRepository { return new Error('과외 내역을 가져올 수 없습니다.'); } } + + async reviewHistory(userId: any) { + try { + const tutoringHistory: Tutoring[] = await this.tutoringModel + .scan({ + teacherId: { eq: userId }, + }) + .exec(); + const history = tutoringHistory + .filter((tutoring) => tutoring.reviewRating != undefined) + .sort((a, b) => { + return new Date(b.endedAt).getTime() - new Date(a.endedAt).getTime(); + }); + + return history.map((tutoring) => { + return { + questionId: tutoring.questionId, + studentId: tutoring.studentId, + tutoringId: tutoring.id, + student: undefined, + reviewRating: tutoring.reviewRating, + reviewComment: tutoring.reviewComment, + startedAt: tutoring.startedAt, + endedAt: tutoring.endedAt, + }; + }); + } catch (error) { + throw new Error('과외 내역을 가져올 수 없습니다.'); + } + } } diff --git a/src/user/descriptions/user.operation.ts b/src/user/descriptions/user.operation.ts index 0264e97..b266819 100644 --- a/src/user/descriptions/user.operation.ts +++ b/src/user/descriptions/user.operation.ts @@ -66,4 +66,19 @@ export const UserOperation = { summary: '다른 사용자의 팔로워 목록 조회', description: '`USER`\n\n다른 사용자의 팔로워 목록을 조회합니다.', }, + tutoringList: { + summary: '과외 내역 조회', + description: '`USER`\n\n과외 내역을 조회합니다.', + }, + bestTeacher: { + summary: '최고의 선생님 조회', + description: '`USER`\n\n최고의 선생님을 조회합니다.', + }, +}; + +export const TeacherOperation = { + reviewList: { + summary: '선생님 리뷰 목록 조회', + description: '`USER`\n\n선생님의 리뷰 목록을 조회합니다.', + }, }; diff --git a/src/user/descriptions/user.param.ts b/src/user/descriptions/user.param.ts index 6e423c0..3f18264 100644 --- a/src/user/descriptions/user.param.ts +++ b/src/user/descriptions/user.param.ts @@ -11,4 +11,10 @@ export const UserParam = { type: String, example: 'kakao', }, + teacherId: { + name: 'teacherId', + description: '선생님 id', + type: String, + example: 'test-teacher-id', + }, }; diff --git a/src/user/user.controller.ts b/src/user/user.controller.ts index 4b59c14..afb4a0b 100644 --- a/src/user/user.controller.ts +++ b/src/user/user.controller.ts @@ -1,5 +1,5 @@ import { AccessToken } from '../auth/entities/auth.entity'; -import { UserOperation } from './descriptions/user.operation'; +import { TeacherOperation, UserOperation } from './descriptions/user.operation'; import { UserParam } from './descriptions/user.param'; import { UserResponse } from './descriptions/user.response'; import { CreateStudentDto, CreateTeacherDto } from './dto/create-user.dto'; @@ -140,8 +140,16 @@ export class UserController { } @ApiTags('User') - @ApiOperation(UserOperation.onlineTeacher) @ApiBearerAuth('Authorization') + @ApiOperation(UserOperation.bestTeacher) + @Get('user/list/teacher/best') + getBestTeachers(@Headers() headers: Headers) { + return this.userService.getBestTeachers(AccessToken.userId(headers)); + } + + @ApiTags('User') + @ApiBearerAuth('Authorization') + @ApiOperation(UserOperation.onlineTeacher) @ApiResponse(UserResponse.onlineTeacher) @Get('user/list/teacher/online') getOnlineTeachers(@Headers() headers: Headers) { @@ -169,14 +177,22 @@ export class UserController { } @ApiTags('User') - @Get('user/history/tutoring/:userId') - tutoringHistory(@Param('userId') userId: string) { - return this.userService.tutoringHistory(userId); + @ApiParam(UserParam.userId) + @ApiOperation(UserOperation.tutoringList) + @Get('user/tutoring/list/:userId') + tutoringList(@Param('userId') userId: string) { + return this.userService.tutoringList(userId); } @ApiTags('Teacher') - @Get('teacher/rating/:teacherId') - teacherRating(@Param('teacherId') teacherId: string) { - return this.userService.teacherRating(teacherId); + @ApiBearerAuth('Authorization') + @ApiParam(UserParam.teacherId) + @ApiOperation(TeacherOperation.reviewList) + @Get('teacher/review/list/:teacherId') + reviewList( + @Headers() headers: Headers, + @Param('teacherId') teacherId: string, + ) { + return this.userService.reviewList(teacherId); } } diff --git a/src/user/user.module.ts b/src/user/user.module.ts index 26ae28e..1fc480b 100644 --- a/src/user/user.module.ts +++ b/src/user/user.module.ts @@ -1,6 +1,7 @@ import { AgoraModule } from '../agora/agora.module'; import { AuthModule } from '../auth/auth.module'; import { dynamooseModule } from '../config.dynamoose'; +import { QuestionRepository } from '../question/question.repository'; import { RedisModule } from '../redis/redis.module'; import { TutoringRepository } from '../tutoring/tutoring.repository'; import { UploadRepository } from '../upload/upload.repository'; @@ -17,6 +18,7 @@ import { Module } from '@nestjs/common'; UserRepository, UploadRepository, TutoringRepository, + QuestionRepository, ], exports: [UserRepository], }) diff --git a/src/user/user.repository.ts b/src/user/user.repository.ts index 7971e47..ec4c8cf 100644 --- a/src/user/user.repository.ts +++ b/src/user/user.repository.ts @@ -351,4 +351,18 @@ export class UserRepository { coin.amount += 1; return await this.userModel.update({ id: userId }, { coin: coin }); } + + async getTeachers() { + try { + return await this.userModel + .scan({ + role: { + eq: 'teacher', + }, + }) + .exec(); + } catch (error) { + throw new Error('선생님 목록을 가져올 수 없습니다.'); + } + } } diff --git a/src/user/user.service.ts b/src/user/user.service.ts index 93047d5..b076cf1 100644 --- a/src/user/user.service.ts +++ b/src/user/user.service.ts @@ -1,5 +1,6 @@ import { AuthRepository } from '../auth/auth.repository'; import { webhook } from '../config.discord-webhook'; +import { QuestionRepository } from '../question/question.repository'; import { RedisRepository } from '../redis/redis.repository'; import { Fail, Success } from '../response'; import { TutoringRepository } from '../tutoring/tutoring.repository'; @@ -25,6 +26,7 @@ export class UserService { private readonly userRepository: UserRepository, private readonly uploadRepository: UploadRepository, private readonly redisRepository: RedisRepository, + private readonly questionRepository: QuestionRepository, private readonly tutoringRepository: TutoringRepository, ) {} @@ -340,6 +342,27 @@ export class UserService { } } + async getBestTeachers(userId: string) { + try { + await this.userRepository.get(userId); + const bestTeachers = await this.userRepository.getTeachers(); + for (const teacher of bestTeachers) { + teacher.rating = await this.tutoringRepository.getTeacherRating( + teacher.id, + ); + } + + bestTeachers.sort((a, b) => b.rating - a.rating); + + return new Success( + '성공적으로 최고의 선생님들을 가져왔습니다.', + bestTeachers, + ); + } catch (error) { + return new Fail(error.message); + } + } + async getOnlineTeachers(userId: string) { try { const users = await this.redisRepository.getAllKeys(); @@ -420,7 +443,7 @@ export class UserService { } } - async tutoringHistory(userId: any) { + async tutoringList(userId: any) { try { const user = await this.userRepository.get(userId); const role = user.role; @@ -435,17 +458,25 @@ export class UserService { } } - async teacherRating(userId: string) { + async reviewList(userId: any) { + const user = await this.userRepository.get(userId); + if (user.role === 'student') { + return new Fail('선생님의 리뷰 내역만 볼 수 있습니다.'); + } + try { - const user = await this.userRepository.get(userId); - if (user.role != 'teacher') { - return new Fail('선생님의 평점만 볼 수 있습니다.'); + const reviewHistory = await this.tutoringRepository.reviewHistory(userId); + + for (const review of reviewHistory) { + review.student = await this.userRepository.getOther(review.studentId); } - const rating = await this.tutoringRepository.getTeacherRating(userId); - return new Success('선생님의 평점을 가져왔습니다.', { rating }); + return new Success('리뷰 내역을 가져왔습니다.', { + count: reviewHistory.length, + history: reviewHistory, + }); } catch (error) { - return new Fail('선생님의 평점을 가져오는데 실패했습니다.'); + return new Fail('리뷰 내역을 가져오는데 실패했습니다.'); } } }