Skip to content

Commit

Permalink
Merge branch 'develop/be' of https://github.com/boostcampwm2023/and06…
Browse files Browse the repository at this point in the history
…-nibobnebob into feature/be-deploy-test
  • Loading branch information
LeeTH916 committed Dec 3, 2023
2 parents 9e25f7d + 96557ac commit cf93887
Show file tree
Hide file tree
Showing 15 changed files with 435 additions and 61 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/be-autodeploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: auto deploy

on:
push:
branches:
- dev

jobs:
push_to_registry:
name: Push to ncp container registry
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to NCP Container Registry
uses: docker/login-action@v2
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
- name: build and push
uses: docker/build-push-action@v3
with:
context: .
file: ./Dockerfile
push: true
tags: ${{ secrets.NCP_CONTAINER_REGISTRY }}/nibobnebob:latest
cache-from: type=registry,ref=${{ secrets.NCP_CONTAINER_REGISTRY }}/nibobnebob:latest
cache-to: type=inline

pull_from_registry:
name: Connect server ssh and pull from container registry
needs: push_to_registry
runs-on: ubuntu-latest
steps:
- name: connect ssh
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.DEV_HOST }}
username: ${{ secrets.DEV_USERNAME }}
password: ${{ secrets.DEV_PASSWORD }}
port: ${{ secrets.DEV_PORT }}
script: |
docker pull ${{ secrets.NCP_CONTAINER_REGISTRY }}/nibobnebob
docker stop $(docker ps -a -q)
docker rm $(docker ps -a -q)
docker run -d -p 8000:80 ${{ secrets.NCP_CONTAINER_REGISTRY }}/nibobnebob
docker image prune -f
23 changes: 23 additions & 0 deletions be/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 베이스 이미지 선택
FROM node:20

# 작업 디렉토리 설정
WORKDIR /usr/src/app

# 종속성 파일 복사 (package.json 및 package-lock.json)
COPY package*.json ./

# 종속성 설치
RUN npm install

# 애플리케이션 소스 코드 복사
COPY . .

# TypeScript 컴파일
RUN npm run build

# 애플리케이션 실행 포트 지정
EXPOSE 8000

# 애플리케이션 실행 명령어
CMD ["node", "dist/src/main"]
2 changes: 1 addition & 1 deletion be/docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,4 @@ services:
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
pgdata:
23 changes: 23 additions & 0 deletions be/dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# production
/build

# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local

npm-debug.log*
yarn-debug.log*
yarn-error.log*
2 changes: 1 addition & 1 deletion be/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,4 @@
],
"coverageDirectory": "../coverage"
}
}
}
14 changes: 14 additions & 0 deletions be/src/restaurant/restaurant.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,12 @@ export class RestaurantRepository extends Repository<RestaurantInfoEntity> {
"current_url.restaurantId = restaurant.id AND current_url.userId = :currentUserId",
{ currentUserId: tokenInfo.id }
)
.leftJoin(
UserWishRestaurantListEntity,
"user_wish_list",
"user_wish_list.restaurantId = restaurant.id AND user_wish_list.userId = :userId",
{ userId: tokenInfo.id }
)
.select([
"restaurant.id",
"restaurant.name",
Expand All @@ -194,6 +200,7 @@ export class RestaurantRepository extends Repository<RestaurantInfoEntity> {
"restaurant.category",
"restaurant.phoneNumber",
'CASE WHEN current_url.user_id IS NOT NULL THEN true ELSE false END AS "isMy"',
`CASE WHEN user_wish_list.userId IS NOT NULL THEN TRUE ELSE FALSE END AS "isWish"`,
"restaurant.reviewCnt",
])
.where(
Expand All @@ -212,6 +219,12 @@ export class RestaurantRepository extends Repository<RestaurantInfoEntity> {
"user_restaurant_list.restaurantId = restaurant.id AND user_restaurant_list.userId = :userId",
{ userId: tokenInfo.id }
)
.leftJoin(
UserWishRestaurantListEntity,
"user_wish_list",
"user_wish_list.restaurantId = restaurant.id AND user_wish_list.userId = :userId",
{ userId: tokenInfo.id }
)
.select([
"restaurant.id",
"restaurant.name",
Expand All @@ -220,6 +233,7 @@ export class RestaurantRepository extends Repository<RestaurantInfoEntity> {
"restaurant.category",
"restaurant.phoneNumber",
'CASE WHEN user_restaurant_list.userId IS NOT NULL THEN TRUE ELSE FALSE END AS "isMy"',
`CASE WHEN user_wish_list.userId IS NOT NULL THEN TRUE ELSE FALSE END AS "isWish"`,
"restaurant.reviewCnt",
])
.where("restaurant.id = :restaurantId", { restaurantId })
Expand Down
17 changes: 10 additions & 7 deletions be/src/restaurant/restaurant.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export class RestaurantService implements OnModuleInit {
private restaurantRepository: RestaurantRepository,
private userRepository: UserRepository,
private reviewRepository: ReviewRepository
) {}
) { }

async searchRestaurant(searchInfoDto: SearchInfoDto, tokenInfo: TokenInfo) {
const restaurants = await this.restaurantRepository.searchRestarant(
Expand Down Expand Up @@ -55,8 +55,9 @@ export class RestaurantService implements OnModuleInit {
tokenInfo
);

const [reviews, reviewCount] = await this.reviewRepository
const reviews = await this.reviewRepository
.createQueryBuilder("review")
.leftJoinAndSelect("review.user", "user")
.select([
"review.id",
"review.isCarVisit",
Expand All @@ -66,14 +67,17 @@ export class RestaurantService implements OnModuleInit {
"review.service",
"review.restroomCleanliness",
"review.overallExperience",
"user.nickName as reviewer",
"review.createdAt"
])
.where("review.restaurant_id = :restaurantId", {
restaurantId: restaurant.restaurant_id,
})
.getManyAndCount();
.getRawMany();

restaurant.restaurant_reviewCnt = reviews.length;
restaurant.reviews = reviews.slice(0, 3);
restaurant.restaurant_reviewCnt = reviewCount;


return restaurant;
}
Expand Down Expand Up @@ -132,9 +136,8 @@ export class RestaurantService implements OnModuleInit {
"+proj=tmerc +lat_0=38 +lon_0=127.0028902777778 +k=1 +x_0=200000 +y_0=500000 +ellps=bessel +units=m +no_defs +towgs84=-115.80,474.99,674.11,1.16,-2.31,-1.63,6.43";
const wgs84 = "EPSG:4326";

const apiUrl = `http://openapi.seoul.go.kr:8088/${key}/json/LOCALDATA_072404/${startPage}/${
startPage + 999
}/`;
const apiUrl = `http://openapi.seoul.go.kr:8088/${key}/json/LOCALDATA_072404/${startPage}/${startPage + 999
}/`;

const response = axios.get(apiUrl);

Expand Down
17 changes: 12 additions & 5 deletions be/src/review/dto/reviewInfo.dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import {
MaxLength,
IsOptional,
MinLength,
Max,
Min,
} from "class-validator";

export class ReviewInfoDto {
Expand All @@ -24,7 +26,8 @@ export class ReviewInfoDto {
})
@IsInt()
@IsOptional()
@MaxLength(1)
@Min(0)
@Max(4)
transportationAccessibility: number | null;

@ApiProperty({
Expand All @@ -33,19 +36,22 @@ export class ReviewInfoDto {
})
@IsInt()
@IsOptional()
@MaxLength(1)
@Min(0)
@Max(4)
parkingArea: number | null;

@ApiProperty({ example: "0", description: "The taste of the food" })
@IsInt()
@IsNotEmpty()
@MaxLength(1)
@Min(0)
@Max(4)
taste: number;

@ApiProperty({ example: "0", description: "The service of the restaurant" })
@IsInt()
@IsNotEmpty()
@MaxLength(1)
@Min(0)
@Max(4)
service: number;

@ApiProperty({
Expand All @@ -54,7 +60,8 @@ export class ReviewInfoDto {
})
@IsInt()
@IsNotEmpty()
@MaxLength(1)
@Min(0)
@Max(4)
restroomCleanliness: number;

@ApiProperty({
Expand Down
7 changes: 4 additions & 3 deletions be/src/user/entities/user.restaurantlist.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import {
ManyToOne,
JoinColumn,
PrimaryColumn,
DeleteDateColumn,
} from "typeorm";
import { User } from "./user.entity";
import { RestaurantInfoEntity } from "src/restaurant/entities/restaurant.entity";
import { ReviewInfoEntity } from "src/review/entities/review.entity";
import { RestaurantInfoEntity } from "../../restaurant/entities/restaurant.entity";
import { ReviewInfoEntity } from "../../review/entities/review.entity";

@Entity("user_restaurant_lists")
export class UserRestaurantListEntity {
Expand All @@ -21,7 +22,7 @@ export class UserRestaurantListEntity {
@CreateDateColumn({ name: "created_at", type: "timestamp" })
createdAt: Date;

@Column({ name: "deleted_at", type: "timestamp", nullable: true })
@DeleteDateColumn({ name: "deleted_at", type: "timestamp", nullable: true })
deletedAt: Date | null;

@ManyToOne(() => User)
Expand Down
5 changes: 3 additions & 2 deletions be/src/user/entities/user.wishrestaurantlist.entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ import {
ManyToOne,
JoinColumn,
PrimaryColumn,
DeleteDateColumn,
} from "typeorm";
import { User } from "./user.entity";
import { RestaurantInfoEntity } from "src/restaurant/entities/restaurant.entity";
import { RestaurantInfoEntity } from "../../restaurant/entities/restaurant.entity";

@Entity("user_wishrestaurant_lists")
export class UserWishRestaurantListEntity {
Expand All @@ -20,7 +21,7 @@ export class UserWishRestaurantListEntity {
@CreateDateColumn({ name: "created_at", type: "timestamp" })
createdAt: Date;

@Column({ name: "deleted_at", type: "timestamp", nullable: true })
@DeleteDateColumn({ name: "deleted_at", type: "timestamp", nullable: true })
deletedAt: Date | null;

@ManyToOne(() => User)
Expand Down
16 changes: 13 additions & 3 deletions be/src/user/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,11 @@ import { AuthGuard } from "@nestjs/passport";
import { SearchInfoDto } from "../restaurant/dto/seachInfo.dto";
import { LocationDto } from "src/restaurant/dto/location.dto";
import { ReviewInfoDto } from "src/review/dto/reviewInfo.dto";
import { ParseArrayPipe } from "../utils/parsearraypipe";

@Controller("user")
export class UserController {
constructor(private userService: UserService) {}
constructor(private userService: UserService) { }

@ApiTags("Mypage")
@Get()
Expand Down Expand Up @@ -79,16 +80,24 @@ export class UserController {
@ApiTags("Follow/Following")
@Get("/autocomplete/:partialUsername")
@UseGuards(AuthGuard("jwt"))
@ApiQuery({
name: 'region',
required: false,
type: String,
isArray: true,
description: '필터링할 지역 목록을 쉼표(,)로 구분하여 제공'
})
@ApiBearerAuth()
@ApiOperation({ summary: "다른 유저 검색 자동완성" })
@ApiResponse({ status: 200, description: "다른 유저 검색 자동완성 완성" })
@ApiResponse({ status: 401, description: "인증 실패" })
@ApiResponse({ status: 400, description: "부적절한 요청" })
async searchTargetUser(
@GetUser() tokenInfo: TokenInfo,
@Param("partialUsername") partialUsername: string
@Param("partialUsername") partialUsername: string,
@Query("region", ParseArrayPipe) region: string[]
) {
return await this.userService.searchTargetUser(tokenInfo, partialUsername);
return await this.userService.searchTargetUser(tokenInfo, partialUsername, region);
}

@ApiTags("Signup", "Mypage")
Expand Down Expand Up @@ -252,6 +261,7 @@ export class UserController {
@ApiResponse({ status: 200, description: "맛집리스트 등록 성공" })
@ApiResponse({ status: 401, description: "인증 실패" })
@ApiResponse({ status: 400, description: "부적절한 요청" })
@UsePipes(new ValidationPipe())
async addRestaurantToNebob(
@Body() reviewInfoDto: ReviewInfoDto,
@GetUser() tokenInfo: TokenInfo,
Expand Down
2 changes: 1 addition & 1 deletion be/src/user/user.repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class UserRepository extends Repository<User> {
select: ["nickName", "region"],
where: { id: In(targetInfoIds) },
});
return { userInfo: userInfo };
return userInfo;
}
async getMypageUserDetailInfo(id: number) {
const userInfo = await this.findOne({
Expand Down
Loading

0 comments on commit cf93887

Please sign in to comment.