diff --git a/src/main/java/com/example/spring_boot_a/api/review/MyReviewController.java b/src/main/java/com/example/spring_boot_a/controller/MyReviewController.java similarity index 80% rename from src/main/java/com/example/spring_boot_a/api/review/MyReviewController.java rename to src/main/java/com/example/spring_boot_a/controller/MyReviewController.java index c7e9219..202ab63 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/MyReviewController.java +++ b/src/main/java/com/example/spring_boot_a/controller/MyReviewController.java @@ -1,7 +1,7 @@ -package com.example.spring_boot_a.api.review; +package com.example.spring_boot_a.controller; -import com.example.spring_boot_a.api.review.dto.MyReviewItemDto; -import com.example.spring_boot_a.domain.service.MyReviewQueryService; +import com.example.spring_boot_a.domain.entity.review.dto.MyReviewItemDto; +import com.example.spring_boot_a.service.MyReviewQueryService; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/example/spring_boot_a/api/review/ReviewController.java b/src/main/java/com/example/spring_boot_a/controller/ReviewController.java similarity index 84% rename from src/main/java/com/example/spring_boot_a/api/review/ReviewController.java rename to src/main/java/com/example/spring_boot_a/controller/ReviewController.java index 769fcc5..1cb0a83 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/ReviewController.java +++ b/src/main/java/com/example/spring_boot_a/controller/ReviewController.java @@ -1,6 +1,10 @@ -package com.example.spring_boot_a.api.review; +package com.example.spring_boot_a.controller; import com.example.spring_boot_a.api.review.dto.*; +import com.example.spring_boot_a.domain.entity.review.dto.ReviewCreateRequest; +import com.example.spring_boot_a.domain.entity.review.dto.ReviewResponse; +import com.example.spring_boot_a.domain.entity.review.dto.StarSummaryResponse; +import com.example.spring_boot_a.service.ReviewService; import jakarta.validation.Valid; import org.springframework.data.domain.*; import org.springframework.web.bind.annotation.*; diff --git a/src/main/java/com/example/spring_boot_a/controller/UserController.java b/src/main/java/com/example/spring_boot_a/controller/UserController.java new file mode 100644 index 0000000..7f8b57d --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/controller/UserController.java @@ -0,0 +1,66 @@ +package com.example.spring_boot_a.controller; + +import com.example.spring_boot_a.domain.entity.user.converter.UserConverter; +import com.example.spring_boot_a.domain.entity.user.dto.UserRequestDto; +import com.example.spring_boot_a.domain.entity.user.dto.UserResponseDto; +import com.example.spring_boot_a.domain.entity.user.User; +import com.example.spring_boot_a.global.apiPayload.code.ApiResponse; +import com.example.spring_boot_a.global.apiPayload.code.GeneralSuccessCode; +import com.example.spring_boot_a.service.UserService; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/users") +public class UserController { + + private final UserService userService; + private final UserConverter userConverter; + + + @PostMapping + public ResponseEntity> createUser( + @Valid @RequestBody UserRequestDto.Create request + ) { + User user = userConverter.toUser(request); + + User saved = userService.createUser(user); + + UserResponseDto.CreateResult responseDTO = userConverter.toCreateResult(saved); + + return ResponseEntity + .status(GeneralSuccessCode.CREATED.getStatus()) + .body(ApiResponse.onSuccess(GeneralSuccessCode.CREATED, responseDTO)); + } + + + @GetMapping("/{userId}") + public ResponseEntity> getUser( + @PathVariable Long userId + ) { + User user = userService.getUser(userId); + + UserResponseDto.Detail dto = userConverter.toDetail(user); + + return ResponseEntity + .status(GeneralSuccessCode.OK.getStatus()) + .body(ApiResponse.onSuccess(GeneralSuccessCode.OK, dto)); + } + + + @GetMapping + public ResponseEntity>> getUsers() { + List users = userService.getUsers(); + + List dtos = userConverter.toSummaryList(users); + + return ResponseEntity + .status(GeneralSuccessCode.OK.getStatus()) + .body(ApiResponse.onSuccess(GeneralSuccessCode.OK, dtos)); + } +} diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Store.java b/src/main/java/com/example/spring_boot_a/domain/entity/Store.java index 22eaeaa..0cc1c6f 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Store.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/Store.java @@ -1,5 +1,8 @@ package com.example.spring_boot_a.domain.entity; +import com.example.spring_boot_a.domain.entity.etc.Location; +import com.example.spring_boot_a.domain.entity.etc.Mission; +import com.example.spring_boot_a.domain.entity.review.Review; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Term.java b/src/main/java/com/example/spring_boot_a/domain/entity/Term.java index 67b0531..fb0b259 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Term.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/Term.java @@ -1,6 +1,7 @@ package com.example.spring_boot_a.domain.entity; import com.example.spring_boot_a.domain.entity.enums.TermType; +import com.example.spring_boot_a.domain.entity.user.UserTerm; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Food.java b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Food.java similarity index 82% rename from src/main/java/com/example/spring_boot_a/domain/entity/Food.java rename to src/main/java/com/example/spring_boot_a/domain/entity/etc/Food.java index 2d131bf..5d87461 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Food.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Food.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.etc; +import com.example.spring_boot_a.domain.entity.user.UserFood; import com.example.spring_boot_a.domain.entity.enums.FoodType; import jakarta.persistence.*; import lombok.Getter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Location.java b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Location.java similarity index 82% rename from src/main/java/com/example/spring_boot_a/domain/entity/Location.java rename to src/main/java/com/example/spring_boot_a/domain/entity/etc/Location.java index 115951e..3b14f94 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Location.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Location.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.etc; +import com.example.spring_boot_a.domain.entity.Store; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Mission.java b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Mission.java similarity index 82% rename from src/main/java/com/example/spring_boot_a/domain/entity/Mission.java rename to src/main/java/com/example/spring_boot_a/domain/entity/etc/Mission.java index ac50cea..9edeb46 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Mission.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Mission.java @@ -1,5 +1,7 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.etc; +import com.example.spring_boot_a.domain.entity.Store; +import com.example.spring_boot_a.domain.entity.user.UserMission; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Reply.java b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Reply.java similarity index 76% rename from src/main/java/com/example/spring_boot_a/domain/entity/Reply.java rename to src/main/java/com/example/spring_boot_a/domain/entity/etc/Reply.java index cbed38e..293b19f 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Reply.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/etc/Reply.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.etc; +import com.example.spring_boot_a.domain.entity.review.Review; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/ReviewPhoto.java b/src/main/java/com/example/spring_boot_a/domain/entity/etc/ReviewPhoto.java similarity index 77% rename from src/main/java/com/example/spring_boot_a/domain/entity/ReviewPhoto.java rename to src/main/java/com/example/spring_boot_a/domain/entity/etc/ReviewPhoto.java index 41a9357..7b2ab0a 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/ReviewPhoto.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/etc/ReviewPhoto.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.etc; +import com.example.spring_boot_a.domain.entity.review.Review; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/Review.java b/src/main/java/com/example/spring_boot_a/domain/entity/review/Review.java similarity index 76% rename from src/main/java/com/example/spring_boot_a/domain/entity/Review.java rename to src/main/java/com/example/spring_boot_a/domain/entity/review/Review.java index 1fdc96d..a97d69b 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/Review.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/review/Review.java @@ -1,5 +1,8 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.review; +import com.example.spring_boot_a.domain.entity.etc.ReviewPhoto; +import com.example.spring_boot_a.domain.entity.Store; +import com.example.spring_boot_a.domain.entity.etc.Reply; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; @@ -25,9 +28,7 @@ public class Review { @ManyToOne(optional = false) @JoinColumn(name = "store_id") private Store store; - @ManyToOne(optional = false) @JoinColumn(name = "user_id") - private User user; - + @JoinColumn(name = "user_id") @OneToMany(mappedBy = "review", cascade = CascadeType.ALL, orphanRemoval = true) private Set photos = new HashSet<>(); diff --git a/src/main/java/com/example/spring_boot_a/api/review/dto/MyReviewItemDto.java b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/MyReviewItemDto.java similarity index 81% rename from src/main/java/com/example/spring_boot_a/api/review/dto/MyReviewItemDto.java rename to src/main/java/com/example/spring_boot_a/domain/entity/review/dto/MyReviewItemDto.java index 67d94db..17e9297 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/dto/MyReviewItemDto.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/MyReviewItemDto.java @@ -1,4 +1,4 @@ -package com.example.spring_boot_a.api.review.dto; +package com.example.spring_boot_a.domain.entity.review.dto; import java.time.Instant; import java.util.List; diff --git a/src/main/java/com/example/spring_boot_a/api/review/dto/ReviewCreateRequest.java b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewCreateRequest.java similarity index 78% rename from src/main/java/com/example/spring_boot_a/api/review/dto/ReviewCreateRequest.java rename to src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewCreateRequest.java index bb6a044..79bbf9c 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/dto/ReviewCreateRequest.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewCreateRequest.java @@ -1,4 +1,4 @@ -package com.example.spring_boot_a.api.review.dto; +package com.example.spring_boot_a.domain.entity.review.dto; import jakarta.validation.constraints.*; import java.util.List; diff --git a/src/main/java/com/example/spring_boot_a/api/review/dto/ReviewResponse.java b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewResponse.java similarity index 81% rename from src/main/java/com/example/spring_boot_a/api/review/dto/ReviewResponse.java rename to src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewResponse.java index e82f2ff..4ef4e3d 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/dto/ReviewResponse.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/ReviewResponse.java @@ -1,4 +1,4 @@ -package com.example.spring_boot_a.api.review.dto; +package com.example.spring_boot_a.domain.entity.review.dto; import java.time.Instant; import java.util.List; diff --git a/src/main/java/com/example/spring_boot_a/api/review/dto/StarSummaryResponse.java b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/StarSummaryResponse.java similarity index 71% rename from src/main/java/com/example/spring_boot_a/api/review/dto/StarSummaryResponse.java rename to src/main/java/com/example/spring_boot_a/domain/entity/review/dto/StarSummaryResponse.java index e587991..8ce6151 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/dto/StarSummaryResponse.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/review/dto/StarSummaryResponse.java @@ -1,4 +1,4 @@ -package com.example.spring_boot_a.api.review.dto; +package com.example.spring_boot_a.domain.entity.review.dto; public record StarSummaryResponse( long s5, diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/User.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/User.java similarity index 95% rename from src/main/java/com/example/spring_boot_a/domain/entity/User.java rename to src/main/java/com/example/spring_boot_a/domain/entity/user/User.java index dbdfce4..dca91ba 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/User.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/User.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.user; +import com.example.spring_boot_a.domain.entity.review.Review; import com.example.spring_boot_a.domain.entity.enums.AddressGu; import com.example.spring_boot_a.domain.entity.enums.Gender; import com.example.spring_boot_a.domain.entity.enums.SocialLoginType; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/UserFood.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserFood.java similarity index 81% rename from src/main/java/com/example/spring_boot_a/domain/entity/UserFood.java rename to src/main/java/com/example/spring_boot_a/domain/entity/user/UserFood.java index 2769156..c25ba2f 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/UserFood.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserFood.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.user; +import com.example.spring_boot_a.domain.entity.etc.Food; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/UserMission.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserMission.java similarity index 83% rename from src/main/java/com/example/spring_boot_a/domain/entity/UserMission.java rename to src/main/java/com/example/spring_boot_a/domain/entity/user/UserMission.java index a59f1a5..60caed3 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/UserMission.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserMission.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.user; +import com.example.spring_boot_a.domain.entity.etc.Mission; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/UserTerm.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserTerm.java similarity index 82% rename from src/main/java/com/example/spring_boot_a/domain/entity/UserTerm.java rename to src/main/java/com/example/spring_boot_a/domain/entity/user/UserTerm.java index 5872f66..7eb2fb8 100644 --- a/src/main/java/com/example/spring_boot_a/domain/entity/UserTerm.java +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/UserTerm.java @@ -1,5 +1,6 @@ -package com.example.spring_boot_a.domain.entity; +package com.example.spring_boot_a.domain.entity.user; +import com.example.spring_boot_a.domain.entity.Term; import jakarta.persistence.*; import lombok.Getter; import lombok.Setter; diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/user/converter/UserConverter.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/converter/UserConverter.java new file mode 100644 index 0000000..e4668e4 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/converter/UserConverter.java @@ -0,0 +1,65 @@ +package com.example.spring_boot_a.domain.entity.user.converter; + +import com.example.spring_boot_a.domain.entity.user.dto.UserRequestDto; +import com.example.spring_boot_a.domain.entity.user.dto.UserResponseDto; +import com.example.spring_boot_a.domain.entity.user.User; +import org.springframework.stereotype.Component; + +import java.time.Instant; +import java.util.List; + +@Component +public class UserConverter { + + public User toUser(UserRequestDto.Create request) { + User user = new User(); + user.setName(request.getName()); + user.setGender(request.getGender()); + user.setBirth(request.getBirth()); + user.setAddress(request.getAddress()); + user.setEmail(request.getEmail()); + user.setPhoneNumber(request.getPhoneNumber()); + user.setSocialType(request.getSocialType()); + user.setPoint(0); + user.setUpdatedAt(Instant.now()); + return user; + } + + public UserResponseDto.CreateResult toCreateResult(User user) { + return UserResponseDto.CreateResult.builder() + .userId(user.getUserId()) + .name(user.getName()) + .email(user.getEmail()) + .build(); + } + + public UserResponseDto.Detail toDetail(User user) { + return UserResponseDto.Detail.builder() + .userId(user.getUserId()) + .name(user.getName()) + .gender(user.getGender()) + .birth(user.getBirth()) + .address(user.getAddress()) + .email(user.getEmail()) + .phoneNumber(user.getPhoneNumber()) + .point(user.getPoint()) + .socialType(user.getSocialType()) + .updatedAt(user.getUpdatedAt()) + .build(); + } + + public UserResponseDto.Summary toSummary(User user) { + return UserResponseDto.Summary.builder() + .userId(user.getUserId()) + .name(user.getName()) + .address(user.getAddress()) + .point(user.getPoint()) + .build(); + } + + public List toSummaryList(List users) { + return users.stream() + .map(this::toSummary) + .toList(); + } +} \ No newline at end of file diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserRequestDto.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserRequestDto.java new file mode 100644 index 0000000..e364bd2 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserRequestDto.java @@ -0,0 +1,43 @@ +package com.example.spring_boot_a.domain.entity.user.dto; + +import com.example.spring_boot_a.domain.entity.enums.AddressGu; +import com.example.spring_boot_a.domain.entity.enums.Gender; +import com.example.spring_boot_a.domain.entity.enums.SocialLoginType; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; + +public class UserRequestDto { + + @Getter + @NoArgsConstructor + public static class Create { + + @NotBlank(message = "이름은 필수값입니다.") + private String name; + + @NotNull(message = "성별은 필수값입니다.") + private Gender gender; + + private LocalDate birth; + + @NotNull(message = "주소(구)는 필수값입니다.") + private AddressGu address; + + @NotBlank(message = "이메일은 필수값입니다.") + @Email(message = "이메일 형식이 올바르지 않습니다.") + private String email; + + @NotBlank(message = "전화번호는 필수값입니다.") + @Size(max = 20, message = "전화번호는 최대 20자입니다.") + private String phoneNumber; + + @NotNull(message = "소셜 타입은 필수값입니다.") + private SocialLoginType socialType; + } +} diff --git a/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserResponseDto.java b/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserResponseDto.java new file mode 100644 index 0000000..bf30f61 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/domain/entity/user/dto/UserResponseDto.java @@ -0,0 +1,45 @@ +package com.example.spring_boot_a.domain.entity.user.dto; + +import com.example.spring_boot_a.domain.entity.enums.AddressGu; +import com.example.spring_boot_a.domain.entity.enums.Gender; +import com.example.spring_boot_a.domain.entity.enums.SocialLoginType; +import lombok.Builder; +import lombok.Getter; + +import java.time.Instant; +import java.time.LocalDate; + +public class UserResponseDto { + + @Getter + @Builder + public static class CreateResult { + private Long userId; + private String name; + private String email; + } + + @Getter + @Builder + public static class Detail { + private Long userId; + private String name; + private Gender gender; + private LocalDate birth; + private AddressGu address; + private String email; + private String phoneNumber; + private Integer point; + private SocialLoginType socialType; + private Instant updatedAt; + } + + @Getter + @Builder + public static class Summary { + private Long userId; + private String name; + private AddressGu address; + private Integer point; + } +} diff --git a/src/main/java/com/example/spring_boot_a/global/apiPayload/code/ApiResponse.java b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/ApiResponse.java new file mode 100644 index 0000000..db66232 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/ApiResponse.java @@ -0,0 +1,50 @@ +package com.example.spring_boot_a.global.apiPayload.code; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +@JsonPropertyOrder({"isSuccess", "code", "message", "result"}) +public class ApiResponse { + + @JsonProperty("isSuccess") + private final Boolean isSuccess; + + @JsonProperty("code") + private final String code; + + @JsonProperty("message") + private final String message; + + @JsonProperty("result") + private T result; + + + public static ApiResponse onSuccess(BaseSuccessCode code, T result) { + return new ApiResponse<>(true, code.getCode(), code.getMessage(), result); + } + + public static ApiResponse onSuccess(BaseSuccessCode code) { + return new ApiResponse<>(true, code.getCode(), code.getMessage(), null); + } + + public static ApiResponse onSuccess(T result) { + return new ApiResponse<>(true, + GeneralSuccessCode.OK.getCode(), + GeneralSuccessCode.OK.getMessage(), + result + ); + } + + public static ApiResponse onFailure(BaseErrorCode code, T result) { + return new ApiResponse<>(false, code.getCode(), code.getMessage(), result); + } + + + public static ApiResponse onFailure(BaseErrorCode code) { + return new ApiResponse<>(false, code.getCode(), code.getMessage(), null); + } +} diff --git a/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseErrorCode.java b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseErrorCode.java new file mode 100644 index 0000000..42ad0f1 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseErrorCode.java @@ -0,0 +1,10 @@ +package com.example.spring_boot_a.global.apiPayload.code; + +import org.springframework.http.HttpStatus; + +public interface BaseErrorCode { + + HttpStatus getStatus(); + String getCode(); + String getMessage(); +} diff --git a/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseSuccessCode.java b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseSuccessCode.java new file mode 100644 index 0000000..8c0bc5c --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/BaseSuccessCode.java @@ -0,0 +1,10 @@ +package com.example.spring_boot_a.global.apiPayload.code; + +import org.springframework.http.HttpStatus; + +public interface BaseSuccessCode { + + HttpStatus getStatus(); + String getCode(); + String getMessage(); +} diff --git a/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralErrorCode.java b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralErrorCode.java new file mode 100644 index 0000000..4ce41a5 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralErrorCode.java @@ -0,0 +1,31 @@ +package com.example.spring_boot_a.global.apiPayload.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum GeneralErrorCode implements BaseErrorCode { + + BAD_REQUEST(HttpStatus.BAD_REQUEST, + "COMMON400_1", + "잘못된 요청입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, + "AUTH401_1", + "인증이 필요합니다."), + FORBIDDEN(HttpStatus.FORBIDDEN, + "AUTH403_1", + "요청이 거부되었습니다."), + NOT_FOUND(HttpStatus.NOT_FOUND, + "COMMON404_1", + "요청한 리소스를 찾을 수 없습니다."), + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, + "COMMON500_1" + ,"서버 에러입니다.") + ; + + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralSuccessCode.java b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralSuccessCode.java new file mode 100644 index 0000000..0116425 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/apiPayload/code/GeneralSuccessCode.java @@ -0,0 +1,24 @@ +package com.example.spring_boot_a.global.apiPayload.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@Getter +@AllArgsConstructor +public enum GeneralSuccessCode implements BaseSuccessCode{ + + OK(HttpStatus.OK, + "COMMON200_1", + "요청이 성공적으로 처리되었습니다."), + CREATED(HttpStatus.CREATED, + "COMMON201_1", + "리소스가 성공적으로 생성되었습니다."), + NO_CONTENT(HttpStatus.NO_CONTENT, + "COMMON204_1", + "성공했지만 반환할 데이터는 없습니다."); + + private final HttpStatus status; + private final String code; + private final String message; +} diff --git a/src/main/java/com/example/spring_boot_a/global/exception/CustomException.java b/src/main/java/com/example/spring_boot_a/global/exception/CustomException.java new file mode 100644 index 0000000..fd865b3 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/exception/CustomException.java @@ -0,0 +1,15 @@ +package com.example.spring_boot_a.global.exception; + +import com.example.spring_boot_a.global.apiPayload.code.BaseErrorCode; +import lombok.Getter; + +@Getter +public class CustomException extends RuntimeException{ + + private final BaseErrorCode errorCode; + + public CustomException(BaseErrorCode errorCode){ + super(errorCode.getMessage()); + this.errorCode = errorCode; + } +} diff --git a/src/main/java/com/example/spring_boot_a/global/exception/GlobalExceptionHandler.java b/src/main/java/com/example/spring_boot_a/global/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..71d28ff --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/global/exception/GlobalExceptionHandler.java @@ -0,0 +1,84 @@ +package com.example.spring_boot_a.global.exception; + +import com.example.spring_boot_a.global.apiPayload.code.ApiResponse; +import com.example.spring_boot_a.global.apiPayload.code.BaseErrorCode; +import com.example.spring_boot_a.global.apiPayload.code.GeneralErrorCode; +import jakarta.persistence.EntityNotFoundException; +import org.springframework.dao.DataIntegrityViolationException; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; + +@RestControllerAdvice +public class GlobalExceptionHandler { + + + @ExceptionHandler(CustomException.class) + public ResponseEntity> handleCustomException(CustomException e) { + BaseErrorCode errorCode = e.getErrorCode(); + + ApiResponse body = ApiResponse.onFailure(errorCode); + + return ResponseEntity + .status(errorCode.getStatus()) + .body(body); + } + + + @ExceptionHandler(EntityNotFoundException.class) + public ResponseEntity> handleEntityNotFound(EntityNotFoundException e) { + + ApiResponse body = ApiResponse.onFailure( + GeneralErrorCode.NOT_FOUND, + e.getMessage() // result에 상세 메시지를 실어 줄 수 있음 + ); + + return ResponseEntity + .status(GeneralErrorCode.NOT_FOUND.getStatus()) + .body(body); + } + + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity> handleValidation(MethodArgumentNotValidException e) { + String msg = e.getBindingResult().getAllErrors().get(0).getDefaultMessage(); + + ApiResponse body = ApiResponse.onFailure( + GeneralErrorCode.BAD_REQUEST, + msg // result에 검증 실패 메시지 + ); + + return ResponseEntity + .status(GeneralErrorCode.BAD_REQUEST.getStatus()) + .body(body); + } + + + @ExceptionHandler(DataIntegrityViolationException.class) + public ResponseEntity> handleIntegrity(DataIntegrityViolationException e) { + + ApiResponse body = ApiResponse.onFailure( + GeneralErrorCode.BAD_REQUEST, + "데이터 제약 조건 위반(중복 등)" + ); + + return ResponseEntity + .status(GeneralErrorCode.BAD_REQUEST.getStatus()) + .body(body); + } + + + @ExceptionHandler(Exception.class) + public ResponseEntity> handleException(Exception e) { + + ApiResponse body = ApiResponse.onFailure( + GeneralErrorCode.INTERNAL_SERVER_ERROR, + e.getMessage() + ); + + return ResponseEntity + .status(GeneralErrorCode.INTERNAL_SERVER_ERROR.getStatus()) + .body(body); + } +} diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/ReplyRepository.java b/src/main/java/com/example/spring_boot_a/repository/ReplyRepository.java similarity index 70% rename from src/main/java/com/example/spring_boot_a/domain/repository/ReplyRepository.java rename to src/main/java/com/example/spring_boot_a/repository/ReplyRepository.java index 839e751..1649a2a 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/ReplyRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/ReplyRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.domain.entity.Reply; +import com.example.spring_boot_a.domain.entity.etc.Reply; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Collection; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewPhotoRepository.java b/src/main/java/com/example/spring_boot_a/repository/ReviewPhotoRepository.java similarity index 70% rename from src/main/java/com/example/spring_boot_a/domain/repository/ReviewPhotoRepository.java rename to src/main/java/com/example/spring_boot_a/repository/ReviewPhotoRepository.java index 269afb0..b6cd176 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewPhotoRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/ReviewPhotoRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.domain.entity.ReviewPhoto; +import com.example.spring_boot_a.domain.entity.etc.ReviewPhoto; import org.springframework.data.jpa.repository.JpaRepository; import java.util.Collection; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepository.java b/src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepository.java similarity index 71% rename from src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepository.java rename to src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepository.java index 1e0975e..6d8a710 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.api.review.dto.MyReviewItemDto; +import com.example.spring_boot_a.domain.entity.review.dto.MyReviewItemDto; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepositoryImpl.java b/src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepositoryImpl.java similarity index 97% rename from src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepositoryImpl.java rename to src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepositoryImpl.java index a38e806..745ea4c 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewQueryRepositoryImpl.java +++ b/src/main/java/com/example/spring_boot_a/repository/ReviewQueryRepositoryImpl.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.api.review.dto.MyReviewItemDto; +import com.example.spring_boot_a.domain.entity.review.dto.MyReviewItemDto; import com.example.spring_boot_a.domain.entity.QReply; import com.example.spring_boot_a.domain.entity.QReview; import com.example.spring_boot_a.domain.entity.QReviewPhoto; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewRepository.java b/src/main/java/com/example/spring_boot_a/repository/ReviewRepository.java similarity index 92% rename from src/main/java/com/example/spring_boot_a/domain/repository/ReviewRepository.java rename to src/main/java/com/example/spring_boot_a/repository/ReviewRepository.java index df6a600..4ad20a9 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/ReviewRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/ReviewRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.domain.entity.Review; +import com.example.spring_boot_a.domain.entity.review.Review; import org.springframework.data.domain.*; import org.springframework.data.jpa.repository.*; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/StoreRepository.java b/src/main/java/com/example/spring_boot_a/repository/StoreRepository.java similarity index 78% rename from src/main/java/com/example/spring_boot_a/domain/repository/StoreRepository.java rename to src/main/java/com/example/spring_boot_a/repository/StoreRepository.java index 324bb86..5debcd8 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/StoreRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/StoreRepository.java @@ -1,4 +1,4 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; import com.example.spring_boot_a.domain.entity.Store; import org.springframework.data.jpa.repository.JpaRepository; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/UserMissionRepository.java b/src/main/java/com/example/spring_boot_a/repository/UserMissionRepository.java similarity index 86% rename from src/main/java/com/example/spring_boot_a/domain/repository/UserMissionRepository.java rename to src/main/java/com/example/spring_boot_a/repository/UserMissionRepository.java index 73b7b6b..e939f42 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/UserMissionRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/UserMissionRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.domain.entity.UserMission; +import com.example.spring_boot_a.domain.entity.user.UserMission; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; diff --git a/src/main/java/com/example/spring_boot_a/domain/repository/UserRepository.java b/src/main/java/com/example/spring_boot_a/repository/UserRepository.java similarity index 55% rename from src/main/java/com/example/spring_boot_a/domain/repository/UserRepository.java rename to src/main/java/com/example/spring_boot_a/repository/UserRepository.java index 83328ca..acfc985 100644 --- a/src/main/java/com/example/spring_boot_a/domain/repository/UserRepository.java +++ b/src/main/java/com/example/spring_boot_a/repository/UserRepository.java @@ -1,6 +1,6 @@ -package com.example.spring_boot_a.domain.repository; +package com.example.spring_boot_a.repository; -import com.example.spring_boot_a.domain.entity.User; +import com.example.spring_boot_a.domain.entity.user.User; import org.springframework.data.jpa.repository.JpaRepository; public interface UserRepository extends JpaRepository { diff --git a/src/main/java/com/example/spring_boot_a/domain/service/MyReviewQueryService.java b/src/main/java/com/example/spring_boot_a/service/MyReviewQueryService.java similarity index 75% rename from src/main/java/com/example/spring_boot_a/domain/service/MyReviewQueryService.java rename to src/main/java/com/example/spring_boot_a/service/MyReviewQueryService.java index b1d5aa0..7e9a6a8 100644 --- a/src/main/java/com/example/spring_boot_a/domain/service/MyReviewQueryService.java +++ b/src/main/java/com/example/spring_boot_a/service/MyReviewQueryService.java @@ -1,7 +1,7 @@ -package com.example.spring_boot_a.domain.service; +package com.example.spring_boot_a.service; -import com.example.spring_boot_a.api.review.dto.MyReviewItemDto; -import com.example.spring_boot_a.domain.repository.ReviewQueryRepository; +import com.example.spring_boot_a.domain.entity.review.dto.MyReviewItemDto; +import com.example.spring_boot_a.repository.ReviewQueryRepository; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.*; import org.springframework.stereotype.Service; diff --git a/src/main/java/com/example/spring_boot_a/api/review/ReviewService.java b/src/main/java/com/example/spring_boot_a/service/ReviewService.java similarity index 89% rename from src/main/java/com/example/spring_boot_a/api/review/ReviewService.java rename to src/main/java/com/example/spring_boot_a/service/ReviewService.java index fb4cb04..1e9f2a4 100644 --- a/src/main/java/com/example/spring_boot_a/api/review/ReviewService.java +++ b/src/main/java/com/example/spring_boot_a/service/ReviewService.java @@ -1,8 +1,14 @@ -package com.example.spring_boot_a.api.review; +package com.example.spring_boot_a.service; -import com.example.spring_boot_a.api.review.dto.*; import com.example.spring_boot_a.domain.entity.*; -import com.example.spring_boot_a.domain.repository.*; +import com.example.spring_boot_a.domain.entity.etc.Reply; +import com.example.spring_boot_a.domain.entity.etc.ReviewPhoto; +import com.example.spring_boot_a.domain.entity.review.Review; +import com.example.spring_boot_a.domain.entity.review.dto.ReviewCreateRequest; +import com.example.spring_boot_a.domain.entity.review.dto.ReviewResponse; +import com.example.spring_boot_a.domain.entity.review.dto.StarSummaryResponse; +import com.example.spring_boot_a.domain.entity.user.User; +import com.example.spring_boot_a.repository.*; import jakarta.persistence.EntityNotFoundException; import org.springframework.data.domain.*; import org.springframework.stereotype.Service; @@ -40,7 +46,6 @@ public Long create(Long userId, Long storeId, ReviewCreateRequest req) { .orElseThrow(() -> new EntityNotFoundException("store not found")); Review r = new Review(); - r.setUser(user); r.setStore(store); r.setStar(req.star()); r.setContent(req.content()); diff --git a/src/main/java/com/example/spring_boot_a/service/UserService.java b/src/main/java/com/example/spring_boot_a/service/UserService.java new file mode 100644 index 0000000..95e2342 --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/service/UserService.java @@ -0,0 +1,14 @@ +package com.example.spring_boot_a.service; + +import com.example.spring_boot_a.domain.entity.user.User; + +import java.util.List; + +public interface UserService { + + User createUser(User user); + + User getUser(Long userId); + + List getUsers(); +} diff --git a/src/main/java/com/example/spring_boot_a/service/UserServiceImpl.java b/src/main/java/com/example/spring_boot_a/service/UserServiceImpl.java new file mode 100644 index 0000000..ff0545c --- /dev/null +++ b/src/main/java/com/example/spring_boot_a/service/UserServiceImpl.java @@ -0,0 +1,39 @@ +package com.example.spring_boot_a.service; + +import com.example.spring_boot_a.domain.entity.user.User; +import com.example.spring_boot_a.repository.UserRepository; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@RequiredArgsConstructor +@Transactional(readOnly = true) +public class UserServiceImpl implements UserService { + + private final UserRepository userRepository; + + + @Override + @Transactional + public User createUser(User user) { + return userRepository.save(user); + } + + + @Override + public User getUser(Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> + new EntityNotFoundException("User not found. id=" + userId)); + } + + + @Override + public List getUsers() { + return userRepository.findAll(); + } +}