Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ST-776, ST-777] 리뷰 목록 엔드포인트 추가 #94

Merged
merged 4 commits into from
Oct 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions src/tutoring/tutoring.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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('과외 내역을 가져올 수 없습니다.');
}
}
}
15 changes: 15 additions & 0 deletions src/user/descriptions/user.operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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선생님의 리뷰 목록을 조회합니다.',
},
};
6 changes: 6 additions & 0 deletions src/user/descriptions/user.param.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,10 @@ export const UserParam = {
type: String,
example: 'kakao',
},
teacherId: {
name: 'teacherId',
description: '선생님 id',
type: String,
example: 'test-teacher-id',
},
};
32 changes: 24 additions & 8 deletions src/user/user.controller.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
2 changes: 2 additions & 0 deletions src/user/user.module.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -17,6 +18,7 @@ import { Module } from '@nestjs/common';
UserRepository,
UploadRepository,
TutoringRepository,
QuestionRepository,
],
exports: [UserRepository],
})
Expand Down
14 changes: 14 additions & 0 deletions src/user/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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('선생님 목록을 가져올 수 없습니다.');
}
}
}
47 changes: 39 additions & 8 deletions src/user/user.service.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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,
) {}

Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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;
Expand All @@ -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('리뷰 내역을 가져오는데 실패했습니다.');
}
}
}