Skip to content

Commit

Permalink
review restaurant adjcent
Browse files Browse the repository at this point in the history
  • Loading branch information
eldpswp99 committed Oct 24, 2023
1 parent ef8edcf commit adb3d2e
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 9 deletions.
6 changes: 6 additions & 0 deletions backend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"class-transformer": "^0.5.1",
"class-validator": "^0.14.0",
"dotenv": "^16.3.1",
"geolib": "^3.3.4",
"jsonwebtoken": "^9.0.2",
"luxon": "^3.4.3",
"multer": "^1.4.5-lts.1",
Expand Down
16 changes: 16 additions & 0 deletions backend/src/review/dtos/in-dtos/review-adjacent-query.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { IsNumber } from 'class-validator';
import { Transform, Type } from 'class-transformer';

export class ReviewAdjacentQueryDto {
@IsNumber()
@Type(() => Number)
latitude: number;

@IsNumber()
@Type(() => Number)
longitude: number;

@IsNumber()
@Type(() => Number)
distance: number;
}
12 changes: 12 additions & 0 deletions backend/src/review/dtos/out-dtos/restaurantList.dto.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { RestaurantDto } from './restaurant.dto';
import { RestaurantEntity } from '../../models/restaurant.entity';

export class RestaurantListDto {
private restaurantList: RestaurantDto[];

constructor(restaurantList: RestaurantEntity[]) {
this.restaurantList = restaurantList.map(
(restaurant) => new RestaurantDto(restaurant),
);
}
}
14 changes: 14 additions & 0 deletions backend/src/review/review.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
NotFoundException,
Param,
Post,
Query,
Req,
UploadedFile,
UseGuards,
Expand All @@ -26,6 +27,8 @@ import { ImageUploadDto } from './dtos/out-dtos/imageUpload.dto';
import { ReviewDetailDto } from './dtos/out-dtos/reviewDetail.dto';
import { UserEntity } from '../user/models/user.entity';
import { UserRepository } from '../user/repostiories/user.repository';
import { ReviewAdjacentQueryDto } from './dtos/in-dtos/review-adjacent-query.dto';
import { RestaurantListDto } from './dtos/out-dtos/restaurantList.dto';

@ApiTags('reviews')
@Controller('reviews')
Expand Down Expand Up @@ -72,6 +75,17 @@ export class ReviewController {
return new ReviewListDto(randomReviews);
}

@UseGuards(JwtAccessGuard)
@Get('/adjacent/restaurants')
async getReviewAdjacent(
@Req() { user }: UserRequest,
@Query() data: ReviewAdjacentQueryDto,
) {
const restaurants = await this.reviewService.getAdjacentRestaurant(data);

return new RestaurantListDto(restaurants);
}

@UseGuards(JwtAccessGuard)
@Get('/:reviewId')
async getReviewDetail(
Expand Down
17 changes: 17 additions & 0 deletions backend/src/review/review.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import { RestaurantRepository } from './repositories/restaurant.repository';
import { ImageRepository } from './repositories/image.repository';
import { In } from 'typeorm';
import { ReviewEntity } from './models/review.entity';
import { ReviewAdjacentQueryDto } from './dtos/in-dtos/review-adjacent-query.dto';
import { getDistance } from 'geolib';

@Injectable()
export class ReviewService {
Expand Down Expand Up @@ -37,4 +39,19 @@ export class ReviewService {
images,
}).save();
}

async getAdjacentRestaurant(data: ReviewAdjacentQueryDto) {
const { longitude, latitude, distance } = data;
const restaurants = await this.restaurantRepository.find({});
const KILOMETER = 1000;

return restaurants.filter(
(restaurant) =>
getDistance(
{ latitude, longitude },
{ latitude: restaurant.latitude, longitude: restaurant.longitude },
) <=
distance * KILOMETER,
);
}
}
126 changes: 126 additions & 0 deletions backend/src/test/review/adjacent-restaurant.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from '../../app.module';
import { Test } from '@nestjs/testing';
import { DataSource } from 'typeorm';
import { appSetting } from '../../main';
import * as supertest from 'supertest';
import { UserEntity } from '../../user/models/user.entity';
import { UserFixture } from '../fixture/user.fixture';
import { HttpStatus } from '@nestjs/common';
import { RestaurantEntity } from '../../review/models/restaurant.entity';
import { RestaurantFixture } from '../fixture/restaurant.fixture';
import { ReviewEntity } from '../../review/models/review.entity';
import { ReviewFixture } from '../fixture/review.fixture';
import { ImageFixture } from '../fixture/image.fixture';
import {
validateRestaurantList,
validateReview,
validateReviewList,
} from './validateReviewList';

describe('Get adjacent restaurant test', () => {
let testServer: NestExpressApplication;
let dataSource: DataSource;
let user: UserEntity;
let accessToken: string;
let restaurant: RestaurantEntity;
let review: ReviewEntity;

beforeAll(async () => {
const module = await Test.createTestingModule({
imports: [AppModule],
}).compile();

testServer = module.createNestApplication<NestExpressApplication>();
dataSource = testServer.get(DataSource);
await dataSource.synchronize(true);
appSetting(testServer);

await testServer.init();
});

beforeEach(async () => {
await dataSource.synchronize(true);

user = await UserFixture.create({
name: 'hi',
username: 'hello',
password: 'world',
});

const { body } = await supertest(testServer.getHttpServer())
.post('/auth/login')
.send({
username: 'hello',
password: 'world',
})
.expect(HttpStatus.CREATED);

accessToken = body.accessToken;

restaurant = await RestaurantFixture.create({});
const image = await ImageFixture.create({});
review = await ReviewFixture.create({
restaurant,
images: [image],
user,
});
});

it('unauthorized', async () => {
await supertest(testServer.getHttpServer())
.get(
`/reviews/adjacent/restaurants?longitude=127.0&latitude=37.0&distance=1`,
)
.expect(HttpStatus.UNAUTHORIZED);
});

it('OK', async () => {
await supertest(testServer.getHttpServer())
.get(
`/reviews/adjacent/restaurants?longitude=127.0&latitude=37.0&distance=1`,
)
.set('Authorization', `Bearer ${accessToken}`)
.expect(HttpStatus.OK);
});

it('DTO check', async () => {
restaurant.longitude = 127.0;
restaurant.latitude = 37.0;
await restaurant.save();

const { body } = await supertest(testServer.getHttpServer())
.get(
`/reviews/adjacent/restaurants?longitude=127.0&latitude=37.0&distance=1`,
)
.set('Authorization', `Bearer ${accessToken}`)
.expect(HttpStatus.OK);

validateRestaurantList(body);
});

// TODO : unittest
it('멀리 떨어지면 안잡한다', async () => {
restaurant.longitude = 127.0;
restaurant.latitude = 37.018018;
await restaurant.save();

const { body } = await supertest(testServer.getHttpServer())
.get(
`/reviews/adjacent/restaurants?longitude=127.0&latitude=37.0&distance=1`,
)
.set('Authorization', `Bearer ${accessToken}`)
.expect(HttpStatus.OK);

expect(body.restaurantList.length).toEqual(0);

const { body: body2 } = await supertest(testServer.getHttpServer())
.get(
`/reviews/adjacent/restaurants?longitude=127.0&latitude=37.0&distance=3`,
)
.set('Authorization', `Bearer ${accessToken}`)
.expect(HttpStatus.OK);

expect(body2.restaurantList.length).toEqual(1);
});
});
7 changes: 7 additions & 0 deletions backend/src/test/review/validateReviewList.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export function validateReview(body: any) {
validateImages(body.images);
}

export function validateRestaurantList(body: any) {
validateDtoKeys(body, ['restaurantList']);
for (const restaurant of body.restaurantList) {
validateRestaurant(restaurant);
}
}

export function validateRestaurant(body: any) {
validateDtoKeys(body, ['id', 'googleMapPlaceId', 'longitude', 'latitude']);
}
Expand Down
9 changes: 0 additions & 9 deletions backend/src/user/repostiories/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,6 @@ export class UserRepository extends Repository<UserEntity> {
return user ? user : undefined; // Return undefined when no user is found
}

async validateUserByToken(payload: JwtPayload) {
const { username } = payload;
const user = await this.findByUsername(username);
if (!user) {
return null;
}
return user;
}

async searchUserByUsernameSorted(name: string) {
return await this.createQueryBuilder('user')
.where('user.name ILIKE :name', { name: `%${name}%` })
Expand Down

0 comments on commit adb3d2e

Please sign in to comment.