-
Notifications
You must be signed in to change notification settings - Fork 248
[π μ¬μ΄ν΄2 - λ―Έμ (μμ½ λ³κ²½/μ·¨μμ μλ¬ μ²λ¦¬)] μ£Όλ(μ΄ν΄μ ) λ―Έμ μ μΆν©λλ€. #433
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
Changes from all commits
045b3d1
8b5f78a
1f28ca5
7f60e6e
c5f06d5
5dab8e0
2e29a42
8f37ae8
ec79b75
7d96a91
99ec61c
65f36bb
703d55a
2d22b22
b33d94e
bc5338e
49a76f4
5daea5b
c944e16
0e393e6
74230be
460f4ea
cf8f788
1f4a41d
9fbc893
5d9410a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,80 @@ | ||
| # μμ½ λ³κ²½/μ·¨μμ μλ¬ μ²λ¦¬ | ||
|
|
||
| ## κΈ°λ₯ ꡬν λͺ©λ‘ | ||
|
|
||
| ### 1λ¨κ³ - μλΉμ€ μ μ± μ μ© | ||
|
|
||
| - [x] μ§λκ° λ μ§μ λν μμ½ μμ± λΆκ° | ||
| - [x] κ°μ λ μ§ + μκ° + ν λ§μ μ΄λ―Έ μμ½μ΄ μμΌλ©΄ μ€λ³΅ μμ½ κ±°λΆ | ||
| - [x] μμ½μ΄ μ‘΄μ¬νλ μκ° μμ λΆκ° (DB μΈλν€ RESTRICT μ€μ ) | ||
| - [x] μ ν¨νμ§ μμ μ λ ₯κ° κ±°λΆ (λΉ μ΄λ¦, null λ μ§/μκ°/ν λ§) | ||
|
|
||
| ### 2λ¨κ³ - μλ¬ μλ΅ μ€κ³ | ||
|
|
||
| - [x] `@RestControllerAdvice`λ‘ μ μ μμΈ μ²λ¦¬ μΆκ° | ||
| - [x] 500 μλ¬κ° μ¬μ©μμκ² λ ΈμΆλμ§ μλλ‘ μ²λ¦¬ | ||
| - [x] μλ¬ μλ΅ λ³Έλ¬Έμ JSON νμμΌλ‘ ν΅μΌ | ||
| - [x] λΈλΌμ°μ μμ μλ¬ λ°μ μ μ¬μ©μμκ² μλ―Έ μλ λ©μμ§ νμ | ||
|
|
||
| ### 3λ¨κ³ - λ΄ μμ½ μ‘°ν/λ³κ²½/μ·¨μ | ||
|
|
||
| - [x] μ΄λ¦μΌλ‘ λ³ΈμΈμ μμ½ λͺ©λ‘ μ‘°ν | ||
| - [x] λ³ΈμΈμ μμ½ μ·¨μ | ||
| - [x] λ³ΈμΈμ μμ½ λ μ§Β·μκ° λ³κ²½ API μΆκ° | ||
| - [x] λ³κ²½ νλ©΄ ꡬν (νλ‘ νΈμλ) | ||
| - [x] λ³κ²½Β·μ·¨μ μλ¬ μΌμ΄μ€ μ²λ¦¬ (μ΄λ―Έ μ§λ μμ½, λ³κ²½νλ €λ μκ°μ΄ μ΄λ―Έ μμ½λ κ²½μ° λ±) | ||
|
|
||
| --- | ||
|
|
||
| ## API λͺ μΈ | ||
|
|
||
| ### μμ½ | ||
|
|
||
| | λ©μλ | URL | μ€λͺ | μ±κ³΅ μλ΅ | | ||
| |---|---|---------------|---| | ||
| | GET | /reservations | μ 체 μμ½ λͺ©λ‘ μ‘°ν | 200 | | ||
| | GET | /reservations/mine?name={name} | μ΄λ¦μΌλ‘ λ΄ μμ½ μ‘°ν | 200 | | ||
| | POST | /reservations | μμ½ μμ± | 201 | | ||
| | DELETE | /reservations/{id} | μμ½ μ·¨μ | 204 | | ||
| | PATCH | /reservations/{id} | μμ½ λ μ§ λ° μκ° λ³κ²½ | 200 | | ||
|
|
||
| ### ν λ§ | ||
|
|
||
| | λ©μλ | URL | μ€λͺ | μ±κ³΅ μλ΅ | | ||
| |---|---|---|---| | ||
| | GET | /themes | μ 체 ν λ§ λͺ©λ‘ μ‘°ν | 200 | | ||
| | GET | /themes/popular | μΈκΈ° ν λ§ μμ 10κ° μ‘°ν (μ΅κ·Ό 1μ£ΌμΌ κΈ°μ€) | 200 | | ||
| | POST | /admin/themes | ν λ§ μμ± | 201 | | ||
| | DELETE | /admin/themes/{id} | ν λ§ μμ | 204 | | ||
|
|
||
| ### μκ° | ||
|
|
||
| | λ©μλ | URL | μ€λͺ | μ±κ³΅ μλ΅ | | ||
| |---|---|---|---| | ||
| | GET | /times | μ 체 μμ½ μκ° λͺ©λ‘ μ‘°ν | 200 | | ||
| | GET | /times/available?date={date}&themeId={themeId} | μμ½ κ°λ₯ν μκ° μ‘°ν | 200 | | ||
| | POST | /admin/times | μμ½ μκ° μμ± | 201 | | ||
| | DELETE | /admin/times/{id} | μμ½ μκ° μμ | 204 | | ||
|
|
||
| --- | ||
|
|
||
| ## μλ¬ μλ΅ μ€κ³ | ||
|
|
||
| ### μλ΅ νμ | ||
|
|
||
| ```json | ||
| { | ||
| "status": "INVALID_DATE", | ||
| "message": "μ΄λ―Έ μμ½λ μκ°μ λλ€." | ||
| } | ||
| ``` | ||
|
|
||
| ### μλ¬ μΌμ΄μ€ | ||
|
|
||
| | μν© | μνμ½λ | | ||
| |---|---| | ||
| | μ€λ³΅ μμ½ | 409 Conflict | | ||
| | μ§λκ° λ μ§ μμ½ | 400 Bad Request | | ||
| | μ‘΄μ¬νμ§ μλ 리μμ€ | 404 Not Found | | ||
| | μμ½μ΄ μ‘΄μ¬νλ μκ°/ν λ§ μμ | 400 Bad Request | | ||
| | μ ν¨νμ§ μμ μ λ ₯κ° | 400 Bad Request | |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package roomescape.config; | ||
|
|
||
| import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer; | ||
| import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer; | ||
| import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; | ||
| import org.springframework.context.annotation.Bean; | ||
| import org.springframework.context.annotation.Configuration; | ||
|
|
||
| import java.time.format.DateTimeFormatter; | ||
|
|
||
| @Configuration | ||
| public class JacksonConfig { | ||
|
|
||
| private static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern("HH:mm"); | ||
|
|
||
| @Bean | ||
| public Jackson2ObjectMapperBuilderCustomizer timeFormatCustomizer() { | ||
| return builder -> { | ||
| builder.serializers(new LocalTimeSerializer(TIME_FORMAT)); | ||
| builder.deserializers(new LocalTimeDeserializer(TIME_FORMAT)); | ||
| }; | ||
| } | ||
| } |
This file was deleted.
This file was deleted.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| package roomescape.dto.reservation; | ||
|
|
||
| import roomescape.exception.InvalidInputException; | ||
|
|
||
| import java.time.LocalDate; | ||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| public record ReservationRequest(String name, LocalDate date, Long timeId, Long themeId) { | ||
|
|
||
| public ReservationRequest { | ||
| List<String> emptyFields = new ArrayList<>(); | ||
|
|
||
| if (name == null || name.isBlank()) { | ||
| emptyFields.add("name"); | ||
| } | ||
|
|
||
| if (date == null) { | ||
| emptyFields.add("date"); | ||
| } | ||
|
|
||
| if (timeId == null) { | ||
| emptyFields.add("timeId"); | ||
| } | ||
|
|
||
| if (themeId == null) { | ||
| emptyFields.add("themeId"); | ||
| } | ||
|
|
||
| if (!emptyFields.isEmpty()) { | ||
| throw new InvalidInputException("%s νλκ° λΉμ΄μμ΅λλ€.".formatted(emptyFields)); | ||
| } | ||
|
Comment on lines
+12
to
+32
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. κ΅Ώ! κΉλνλ€μ!! |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| package roomescape.dto.reservationtime; | ||
|
|
||
| import roomescape.exception.InvalidInputException; | ||
|
|
||
| import java.time.LocalTime; | ||
|
|
||
| public record ReservationTimeRequest(LocalTime startAt) { | ||
|
|
||
| public ReservationTimeRequest { | ||
| validateStartAt(startAt); | ||
| } | ||
|
|
||
| @Override | ||
| public LocalTime startAt() { | ||
| return startAt; | ||
| } | ||
|
|
||
| private static void validateStartAt(LocalTime startAt) { | ||
| if (startAt == null) { | ||
| throw new InvalidInputException("μμ± μκ°μ νμμ λλ€."); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| package roomescape.domain.theme; | ||
| package roomescape.dto.theme; | ||
|
|
||
| public record ThemeRequest(String name, String description, String url) { | ||
|
Comment on lines
+1
to
3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. μ¬κΈ°λ κ²μ¦μ΄ νμνμ§ μμκΉμ? null κ°μ΄ λ€μ΄μ€λ κ²½μ°κ° μμ κ² κ°μμ! |
||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| package roomescape.exception; | ||
|
|
||
| public record ErrorResponse(String errorCode, String message) { | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| package roomescape.exception; | ||
|
|
||
| import org.springframework.http.HttpStatus; | ||
| import org.springframework.http.ResponseEntity; | ||
| import org.springframework.web.bind.annotation.ExceptionHandler; | ||
| import org.springframework.web.bind.annotation.RestControllerAdvice; | ||
|
|
||
| @RestControllerAdvice | ||
| public class GlobalExceptionHandler { | ||
|
|
||
| @ExceptionHandler(ReservationAlreadyExistException.class) | ||
| public ResponseEntity<ErrorResponse> handle(ReservationAlreadyExistException e) { | ||
| return ResponseEntity.status(HttpStatus.CONFLICT) | ||
| .body(new ErrorResponse("DUPLICATE_RESERVATION", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(ReservationNotFoundException.class) | ||
| public ResponseEntity<ErrorResponse> handle(ReservationNotFoundException e) { | ||
| return ResponseEntity.status(HttpStatus.NOT_FOUND) | ||
| .body(new ErrorResponse("RESERVATION_NOT_FOUND", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(ReservationTimeNotFoundException.class) | ||
| public ResponseEntity<ErrorResponse> handle(ReservationTimeNotFoundException e) { | ||
| return ResponseEntity.status(HttpStatus.NOT_FOUND) | ||
| .body(new ErrorResponse("TIME_NOT_FOUND", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(ThemeNotFoundException.class) | ||
| public ResponseEntity<ErrorResponse> handle(ThemeNotFoundException e) { | ||
| return ResponseEntity.status(HttpStatus.NOT_FOUND) | ||
| .body(new ErrorResponse("THEME_NOT_FOUND", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(InvalidReservationException.class) | ||
| public ResponseEntity<ErrorResponse> handle(InvalidReservationException e) { | ||
| return ResponseEntity.status(HttpStatus.BAD_REQUEST) | ||
| .body(new ErrorResponse("INVALID_DATE_OR_TIME", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(ReferencedDataException.class) | ||
| public ResponseEntity<ErrorResponse> handle(ReferencedDataException e) { | ||
| return ResponseEntity.status(HttpStatus.BAD_REQUEST) | ||
| .body(new ErrorResponse("DIFFERENCE_DATA_EXISTS", e.getMessage())); | ||
| } | ||
|
|
||
| @ExceptionHandler(InvalidInputException.class) | ||
| public ResponseEntity<ErrorResponse> handle(InvalidInputException e) { | ||
| return ResponseEntity.status(HttpStatus.BAD_REQUEST) | ||
| .body(new ErrorResponse("INVALID_INPUT", e.getMessage())); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package roomescape.exception; | ||
|
|
||
| public class InvalidInputException extends IllegalArgumentException { | ||
| public InvalidInputException(String message) { | ||
| super(message); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package roomescape.exception; | ||
|
|
||
| public class InvalidReservationException extends RuntimeException { | ||
| public InvalidReservationException() { | ||
| super("μ΄λ―Έ μ§λ λ μ§μ΄κ±°λ μκ°μ λλ€."); | ||
| } | ||
| } |
Uh oh!
There was an error while loading. Please reload this page.