Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e9de564
add: gitignore 추가
HyunTaek5 Feb 25, 2023
6d6471a
add: docker-compose mysql 셋업
HyunTaek5 Feb 25, 2023
2442ae6
init: spring project init
HyunTaek5 Feb 25, 2023
de92dcf
add: BaseEntity 추가
HyunTaek5 Feb 25, 2023
fbc3e06
add: 레스토랑, 리뷰 entity 추가
HyunTaek5 Feb 25, 2023
9a24918
fix: db 세팅 환경변수 수정
HyunTaek5 Feb 25, 2023
00da579
fix: mysql docker-compose 포트 수정
HyunTaek5 Feb 25, 2023
45360f6
fix: Restaurant 엔티티 칼럼 수정
HyunTaek5 Feb 25, 2023
3234246
chore: spring docs 추가
HyunTaek5 Feb 25, 2023
aa3b79a
feat: 레스토랑 생성 api 구현
HyunTaek5 Feb 25, 2023
43fabdb
add: 예외처리 핸들러 구현
HyunTaek5 Feb 25, 2023
3f2dc98
feat: 레스토랑 단일 조회 api 구현
HyunTaek5 Feb 25, 2023
87283cf
feat: 레스토랑 수정 api 구현
HyunTaek5 Feb 25, 2023
2d941bb
feat: 레스토랑 목록 조회 api 구현
HyunTaek5 Feb 25, 2023
5dfd1c9
feat: 리뷰 생성 api 구현
HyunTaek5 Feb 25, 2023
c463b9e
feat: 레스토랑 목록 조회 api 구현
HyunTaek5 Feb 25, 2023
8d7b5ff
feat: 리뷰 목록 조회 api 구현
HyunTaek5 Feb 25, 2023
c558ecc
feat: 리뷰 조회 api 구현
HyunTaek5 Feb 25, 2023
1a701af
feat: 리뷰 수정 api 구현
HyunTaek5 Feb 25, 2023
e594f6b
feat: 리뷰 삭제 api 구현
HyunTaek5 Feb 25, 2023
f3bb563
feat: 레스토랑 삭제 api 구현
HyunTaek5 Feb 25, 2023
18613df
chore: swagger summary 수정
HyunTaek5 Feb 25, 2023
40963ec
chore: README 업데이트
HyunTaek5 Feb 25, 2023
3bc9071
fix: findAll isDeleted 필터링 추가
HyunTaek5 Feb 26, 2023
99af100
fix: 리뷰 조회 LIKE 조건 수정
HyunTaek5 Feb 26, 2023
549dd99
chore: gradle 파일 추가
HyunTaek5 Feb 26, 2023
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
37 changes: 37 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
.gradle
build/
!gradle/wrapper/gradle-wrapper.jar
!**/src/main/**/build/
!**/src/test/**/build/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
bin/
!**/src/main/**/bin/
!**/src/test/**/bin/

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
out/
!**/src/main/**/out/
!**/src/test/**/out/

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/

### VS Code ###
.vscode/
application-jwt.properties
30 changes: 20 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,50 +23,60 @@

## 기능

### 리뷰 목록 조회
### 리뷰 목록 조회 [완료]

- 레스토랑 명, 리뷰 리스트를 내용을 반환합니다.
- 리뷰 리스트는 등록 순이나 역순으로 조회할 수 있고 pagination을 지원하며, 리뷰 제목과 내용으로 검색할 수 있습니다.

### 리뷰 조회
### 리뷰 조회 [ 완료 ]

- 하나의 레스토랑명, 리뷰 제목, 리뷰 내용이 반환합니다.

### 리뷰 수정
### 리뷰 수정 [ 완료 ]

- 리뷰를 수정할 수 있습니다.

### 리뷰 작성
### 리뷰 작성 [ 완료 ]

- 리뷰에는 제목과 내용이 있습니다.

### 리뷰 삭제
### 리뷰 삭제 [ 완료 ]

- 리뷰 삭제에서는 하나의 리뷰를 삭제합니다.
- Hard Delete를 통해 데이터를 삭제합니다.

### 레스토랑 등록
### 레스토랑 등록 [완료]

- 레스토랑에는 레스토랑명, 레스토랑 카테고리 (한식, 중식, 일식 등)의 내용이 있습니다.
- 등록한 날짜를 기록해야 합니다.

### 레스토랑 수정
### 레스토랑 수정 [완료]

- 레스토랑의 카테고리만 변경할 수 있습니다.

### 레스토랑 목록 조회
### 레스토랑 목록 조회 [완료]

- 레스토랑의 전체 목록을 조회할 수 있습니다.
- 레스토랑 카테고리에 따른 레스토랑 목록 조회를 할 수 있습니다.

### 레스토랑 조회
### 레스토랑 조회 [완료]

- 레스토랑 명, 카테고리, 음식점의 생성 일자가 반환 되어야 합니다.

### 레스토랑 삭제
### 레스토랑 삭제 [ 완료 ]

- 레스토랑의 삭제로 인하여 작성된 리뷰들이 삭제 되면 안됩니다. (Soft Delete)

## 디렉토리 구조

### /api
> Controller, Config을 관리
### /application
> Service, dto 관련 비즈니스 로직을 관리
### /domain
> Entity, Repository을 관리


# 기여해주신 분

- [김기현](https://github.com/kim1387) ✨
Expand Down
11 changes: 11 additions & 0 deletions api/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
dependencies {
implementation project(":application")

implementation'org.springframework.boot:spring-boot-starter-web:2.6.3'
implementation 'org.springdoc:springdoc-openapi-ui:1.6.6'
implementation group : 'org.apache.logging.log4j', name: 'log4j-web', version: '2.17.1'

testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.3'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
13 changes: 13 additions & 0 deletions api/src/main/java/com/techeer/GoodNightApiApplication.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.techeer;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;

@SpringBootApplication
@EnableJpaAuditing
public class GoodNightApiApplication {
public static void main(String[] args) {
SpringApplication.run(GoodNightApiApplication.class, args);
}
}
25 changes: 25 additions & 0 deletions api/src/main/java/com/techeer/config/SwaggerConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.techeer.config;

import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import org.springdoc.core.GroupedOpenApi;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class SwaggerConfig {
@Bean
public GroupedOpenApi publicApi() {
return GroupedOpenApi.builder()
.group("v1")
.pathsToMatch("/api/**")
.build();
}
@Bean
public OpenAPI springShopOpenAPI() {
return new OpenAPI()
.info(new Info().title("Good Night Hackathon API")
.description("테커 Good Night 스프링 해커톤 API 명세서입니다.")
.version("v0.0.1"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package com.techeer.controller.restaurant;

import com.techeer.persistence.restaurant.application.RestaurantService;

import com.techeer.persistence.restaurant.dto.request.CreateRestaurantReq;
import com.techeer.persistence.restaurant.dto.request.PatchRestaurantReq;
import com.techeer.persistence.restaurant.dto.response.RestaurantDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Optional;

@Tag(name = "restaurants", description = "레스토랑 API")
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/restaurants")
public class RestaurantController {

@Resource(name = "restaurantService")
private final RestaurantService restaurantService;

@Operation(summary = "getRestaurant", description = "레스토랑 목록 조회")
@GetMapping()
public ResponseEntity<Page<RestaurantDTO>> get(
@PageableDefault(sort ="id", direction = Sort.Direction.DESC)
Pageable pageable,
@RequestParam(value = "categoryName", required = false) Optional<String> categoryName
) {
return new ResponseEntity<>(restaurantService.getRestaurants(pageable, categoryName), HttpStatus.OK);
}


@Operation(summary = "createRestaurant", description = "레스토랑 등록")
@ApiResponses({
@ApiResponse(responseCode = "201", description = "CREATED",
content = @Content(schema = @Schema(implementation = RestaurantDTO.class)))
})
@PostMapping()
public ResponseEntity<RestaurantDTO> create(
@RequestBody final CreateRestaurantReq createRestaurantReq
) {
return new ResponseEntity<>(restaurantService.create(createRestaurantReq), HttpStatus.CREATED);
}

@Operation(summary = "getRestaurantById", description = "레스토랑 조회")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "OK",
content = @Content(schema = @Schema(implementation = RestaurantDTO.class))),
@ApiResponse(responseCode = "-200", description = "RESTAURANT_ID_NOT_FOUND"),
})
@GetMapping("/{id}")
public ResponseEntity<RestaurantDTO> getRestaurantById(@PathVariable final long id) {
return new ResponseEntity<>(restaurantService.findById(id), HttpStatus.OK);
}

@Operation(summary = "patchRestaurantById", description = "레스토랑 수정")
@PatchMapping("/{id}")
public ResponseEntity<RestaurantDTO> patchRestaurantById(
@PathVariable final long id,
@RequestBody final PatchRestaurantReq patchRestaurantReq) {
return new ResponseEntity<>(restaurantService.patchById(id, patchRestaurantReq), HttpStatus.OK);
}

@Operation(summary = "deleteRestaurantById", description = "레스토랑 삭제")
@DeleteMapping("/{id}")
public void deleteRestaurantById(@PathVariable final long id) {
restaurantService.deleteById(id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.techeer.controller.review;

import com.techeer.persistence.review.application.ReviewService;
import com.techeer.persistence.review.dto.request.PatchReviewReq;
import com.techeer.persistence.review.dto.request.ReviewReq;
import com.techeer.persistence.review.dto.response.ReviewDTO;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.Optional;

@Tag(name = "reviews", description = "리뷰 API")
@Slf4j
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/reviews")
public class ReviewController {

@Resource(name = "reviewService")
private final ReviewService reviewService;

@Operation(summary = "getReviews", description = "리뷰 목록 조회")
@GetMapping()
public ResponseEntity<Page<ReviewDTO>> getReviews(
@PageableDefault(sort = "id", direction = Sort.Direction.DESC)Pageable pageable,
@RequestParam(value = "keyword", required = false) Optional<String> keyword
) {
return new ResponseEntity<>(reviewService.findAll(pageable, keyword), HttpStatus.OK);
}


@Operation(summary = "createReview", description = "리뷰 생성")
@PostMapping()
public ResponseEntity<ReviewDTO> create(@RequestBody final ReviewReq reviewReq) {
return new ResponseEntity<>(reviewService.create(reviewReq), HttpStatus.CREATED);
}

@Operation(summary = "getReviewById", description = "리뷰 조회")
@GetMapping("/{id}")
public ResponseEntity<ReviewDTO> getReview(@PathVariable long id) {
return new ResponseEntity<>(reviewService.findById(id), HttpStatus.OK);
}

@Operation(summary = "patchReviewById", description = "리뷰 수정")
@PatchMapping("/{id}")
public ResponseEntity<ReviewDTO> patchReview(
@PathVariable long id,
@RequestBody PatchReviewReq patchReviewReq) {
return new ResponseEntity<>(reviewService.patchById(id, patchReviewReq), HttpStatus.OK);
}

@Operation(summary = "deleteReviewById", description = "리뷰 삭제")
@DeleteMapping("/{id}")
public void deleteReview(@PathVariable long id) {
reviewService.deleteById(id);
}
}
48 changes: 48 additions & 0 deletions api/src/main/resources/application.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
db.type: mysql
db.host: localhost
db.port: 33080
db.database: good-night-dev-db
db.timezone: Asia/Seoul


spring:
datasource:
tomcat:
jmx-enabled: true
application:
name: api
debug: true
jpa:
generate-ddl: true

springdoc:
swagger-ui:
path: /swagger-ui.html
groups-order: DESC
operationsSorter: method
disable-swagger-default-url: true
display-request-duration: true
api-docs:
path: /api-docs
show-actuator: true
default-consumes-media-type: application/json
default-produces-media-type: application/json
paths-to-match:
- /api/**

spring.datasource:
username: user
password: password
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:${db.type}://${db.host}:${db.port}/${db.database}?serverTimezone=${db.timezone}&characterEncoding=UTF-8

spring.jpa:
database: mysql
show-sql: false
hibernate:
dialect: org.hibernate.dialect.MySQL57InnoDBDialect
ddl-auto: update


server:
port: 8000
12 changes: 12 additions & 0 deletions application/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
dependencies {
implementation project(":domain")

implementation 'org.springframework.boot:spring-boot-starter-data-jpa:2.6.6'
implementation'org.springframework.boot:spring-boot-starter-web:2.6.3'

implementation group : 'org.apache.logging.log4j', name: 'log4j-api', version: '2.17.1'

testImplementation 'org.springframework.boot:spring-boot-starter-test:2.6.3'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.2'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.2'
}
Loading