diff --git a/src/apis/reservations/dto/return-reservation.output.ts b/src/apis/reservations/dto/return-reservation.output.ts new file mode 100644 index 0000000..f02c61d --- /dev/null +++ b/src/apis/reservations/dto/return-reservation.output.ts @@ -0,0 +1,12 @@ +import { Field, ObjectType } from '@nestjs/graphql'; +import { Review } from 'src/apis/reviews/entities/review.entity'; +import { User } from 'src/apis/users/entities/user.entity'; + +@ObjectType() +export class returnUserWithReviewOutput { + @Field(() => User) + profile: User; + + @Field(() => Review) + review: Review; +} diff --git a/src/apis/reservations/interfaces/reservations-service.interface.ts b/src/apis/reservations/interfaces/reservations-service.interface.ts index b3f87f6..9054998 100644 --- a/src/apis/reservations/interfaces/reservations-service.interface.ts +++ b/src/apis/reservations/interfaces/reservations-service.interface.ts @@ -37,3 +37,7 @@ export interface IReservationsServiceFindAllByUserId { export interface IReservationsServiceFindAllByShopId { shopId: string; } + +export interface IReservationsServiceFindForShopDetailPage { + shopId: string; +} diff --git a/src/apis/reservations/reservation.module.ts b/src/apis/reservations/reservation.module.ts index 297d307..4426a90 100644 --- a/src/apis/reservations/reservation.module.ts +++ b/src/apis/reservations/reservation.module.ts @@ -2,6 +2,8 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { DogsService } from '../dogs/dogs.service'; import { Dog } from '../dogs/entities/dog.entity'; +import { Review } from '../reviews/entities/review.entity'; +import { ReviewsService } from '../reviews/reviews.service'; import { Shop } from '../shops/entities/shop.entity'; import { ShopsService } from '../shops/shops.service'; import { User } from '../users/entities/user.entity'; @@ -14,6 +16,7 @@ import { ReservationsService } from './reservation.service'; imports: [ TypeOrmModule.forFeature([ Reservation, // + Review, User, Shop, Dog, @@ -22,6 +25,7 @@ import { ReservationsService } from './reservation.service'; providers: [ ReservationsResolver, // ReservationsService, + ReviewsService, ShopsService, UsersService, DogsService, diff --git a/src/apis/reservations/reservation.resolver.ts b/src/apis/reservations/reservation.resolver.ts index 1b04123..d668fe2 100644 --- a/src/apis/reservations/reservation.resolver.ts +++ b/src/apis/reservations/reservation.resolver.ts @@ -3,6 +3,7 @@ import { Args, Context, Mutation, Query, Resolver } from '@nestjs/graphql'; import { IContext } from 'src/commons/interface/context'; import { GqlAuthGuard } from '../auth/guards/gql-auth.guard'; import { CreateReservationInput } from './dto/create-reservation.input'; +import { returnUserWithReviewOutput } from './dto/return-reservation.output'; import { Reservation } from './entities/reservation.entity'; import { ReservationsService } from './reservation.service'; @@ -51,11 +52,20 @@ export class ReservationsResolver { description: 'Return : 한 가게의 예약 정보', }) fetchReservationsByShop( - @Context() context: IContext, // + @Args('shopId') shopId: string, // ): Promise { - const userId = context.req.user.id; - console.log(userId, '@@@@'); - return this.reservationsService.findAllByUserId({ userId }); + return this.reservationsService.findAllByShopId({ shopId }); + } + + // 가게의 모든 예약과 예약자 가져오기 + @Query(() => [returnUserWithReviewOutput], { + description: + 'Return : { profile: 회원정보 , review: 그 회원이 작성한 리뷰 } 형식의 객체들이 모인 배열', + }) + fetchForShopDetailPage( + @Args('shopId') shopId: string, // + ): Promise { + return this.reservationsService.findForShopDetailPage({ shopId }); } //예약 삭제하기 diff --git a/src/apis/reservations/reservation.service.ts b/src/apis/reservations/reservation.service.ts index c19548d..6ec1d3c 100644 --- a/src/apis/reservations/reservation.service.ts +++ b/src/apis/reservations/reservation.service.ts @@ -6,8 +6,12 @@ import { import { InjectRepository } from '@nestjs/typeorm'; import { Repository } from 'typeorm'; import { DogsService } from '../dogs/dogs.service'; +import { Review } from '../reviews/entities/review.entity'; +import { ReviewsService } from '../reviews/reviews.service'; import { ShopsService } from '../shops/shops.service'; +import { User } from '../users/entities/user.entity'; import { UsersService } from '../users/user.service'; +import { returnUserWithReviewOutput } from './dto/return-reservation.output'; import { Reservation } from './entities/reservation.entity'; import { IReservationsServiceCheckDuplication, @@ -17,6 +21,7 @@ import { IReservationsServiceFindAllByUserId, IReservationsServiceFindById, IReservationsServiceFindDeletedById, + IReservationsServiceFindForShopDetailPage, } from './interfaces/reservations-service.interface'; @Injectable() @@ -27,6 +32,8 @@ export class ReservationsService { private readonly usersService: UsersService, private readonly shopsService: ShopsService, private readonly dogsService: DogsService, + @InjectRepository(Review) + private readonly reviewsRepository: Repository, ) {} // 신규 예약 정보 생성 @@ -150,6 +157,58 @@ export class ReservationsService { return result; } + // 가게 상세페이지용 : 가게의 모든 리뷰작성자 프로필과 리뷰 가져오기 + async findForShopDetailPage({ + shopId, + }: IReservationsServiceFindForShopDetailPage): Promise< + returnUserWithReviewOutput[] + > { + // 해당 가게의 예약들 + const myBooks = await this.reservationsRepository.find({ + where: { shop: { id: shopId } }, + relations: ['shop', 'user'], + }); + // 예약과 연결된 유저ID들 + const userIds = []; + const userIds1 = myBooks.forEach((el) => { + if (!userIds.includes(el.user.id)) { + userIds.push(el.user.id); + } + }); + + // 예약의 리뷰들 + const myReviews: Review[] = []; + for (let i = 0; i < myBooks.length; i++) { + const reviews = await this.reviewsRepository.find({ + where: { shop: { id: shopId }, reservation: { id: myBooks[i].id } }, + relations: ['shop', 'reservation'], + }); + if (reviews[0] !== undefined) { + myReviews.push(reviews[0]); + } + } + + const fetchList: returnUserWithReviewOutput[] = []; + // 유저-리뷰 매핑 // 가독성을 위해 우선 for문 사용 + for (let i = 0; i < userIds.length; i++) { + for (let j = 0; j < myReviews.length; j++) { + const resultBook = await this.reservationsRepository.find({ + where: { + shop: { id: shopId }, + user: { id: userIds[i] }, + }, + relations: ['user'], + }); + const _user = resultBook[0].user; + const _review = myReviews[j]; + if (resultBook[0].id === myReviews[0].reservation.id) + fetchList.push({ profile: _user, review: _review }); + } + } + + return fetchList; + } + //예약 삭제하기 async delete({ reservationId, diff --git a/src/apis/reviews/__test__/reviews.resolver.spec.ts b/src/apis/reviews/__test__/reviews.resolver.spec.ts new file mode 100644 index 0000000..498be87 --- /dev/null +++ b/src/apis/reviews/__test__/reviews.resolver.spec.ts @@ -0,0 +1,35 @@ +import { Test, TestingModule } from '@nestjs/testing'; +import { Review } from '../entities/review.entity'; +import { ReviewsResolver } from '../reviews.resolver'; +import { ReviewsService } from '../reviews.service'; + +jest.mock('../reviews.service'); + +const EXAMPLE_REVIEW: Review = { + // +}; + +describe('ReviewResolver', () => { + let mockReviewsService: ReviewsService; + let reviewsResolver: ReviewsResolver; + + beforeEach(async () => { + const reviewsModule: TestingModule = await Test.createTestingModule({ + providers: [ + ReviewsResolver, + { + provide: ReviewsService, + useValue: mockReviewsService, + }, + ], + }).compile(); + mockReviewsService = reviewsModule.get(ReviewsService); + reviewsResolver = reviewsResolver.get(ReviewsResolver); + }); + + describe('fetchReview', () => { + it('reivewService의 find 메서드 실행', async () => { + await reviewsResolver.fetchReview({ reviewId }); + }); + }); +}); diff --git a/src/apis/reviews/entities/review.entity.ts b/src/apis/reviews/entities/review.entity.ts index 453c608..71f580d 100644 --- a/src/apis/reviews/entities/review.entity.ts +++ b/src/apis/reviews/entities/review.entity.ts @@ -24,7 +24,7 @@ export class Review { @CreateDateColumn({ nullable: true }) @Field(() => Date) - createAt: Date; + createdAt: Date; @Column() @Field(() => Float) diff --git a/src/apis/reviews/interfaces/reviews-service.interface.ts b/src/apis/reviews/interfaces/reviews-service.interface.ts index 3fbfbed..181aa88 100644 --- a/src/apis/reviews/interfaces/reviews-service.interface.ts +++ b/src/apis/reviews/interfaces/reviews-service.interface.ts @@ -16,4 +16,5 @@ export interface IReviewServiceFindByUserId { export interface IReviewServiceFindByShopId { shopId: string; page: number; + count: number; } diff --git a/src/apis/reviews/reviews.resolver.ts b/src/apis/reviews/reviews.resolver.ts index 63a96bd..e88389b 100644 --- a/src/apis/reviews/reviews.resolver.ts +++ b/src/apis/reviews/reviews.resolver.ts @@ -27,10 +27,16 @@ export class ReviewsResolver { async fetchReviewsByShopId( @Args({ name: 'page', defaultValue: 1, nullable: true }) page: number, // + @Args({ name: 'page', defaultValue: 1, nullable: true }) + count: number, // @Args('shopId') shopId: string, // ): Promise { - return await this.reviewsService.findByShopId({ page, shopId }); + return await this.reviewsService.findByShopIdWithPage({ + page, + count, + shopId, + }); } @UseGuards(GqlAuthGuard('access')) diff --git a/src/apis/reviews/reviews.service.ts b/src/apis/reviews/reviews.service.ts index 86663b9..cfacedc 100644 --- a/src/apis/reviews/reviews.service.ts +++ b/src/apis/reviews/reviews.service.ts @@ -33,9 +33,10 @@ export class ReviewsService { } // 가게의 모든 리뷰 가져오기 - async findByShopId({ + async findByShopIdWithPage({ page, - shopId, // + count, // + shopId, }: IReviewServiceFindByShopId): Promise { const checkShop = await this.shopsService.findById({ shopId }); if (!checkShop) { @@ -43,13 +44,14 @@ export class ReviewsService { } const result = await this.reviewsRepository.find({ where: { shop: { id: shopId } }, - skip: (page - 1) * 4, - take: 4, + skip: (page - 1) * count, + take: count, order: { - createAt: 'ASC', + createdAt: 'ASC', }, + relations: ['shop', 'reservation'], }); - console.log(result); + return result; }