diff --git a/src/main/java/com/readyvery/readyverydemo/domain/Store.java b/src/main/java/com/readyvery/readyverydemo/domain/Store.java index 691d2e5..929bdc3 100644 --- a/src/main/java/com/readyvery/readyverydemo/domain/Store.java +++ b/src/main/java/com/readyvery/readyverydemo/domain/Store.java @@ -77,4 +77,6 @@ public class Store extends BaseTimeEntity { @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) private List carts = new ArrayList<>(); + @OneToMany(mappedBy = "store", cascade = CascadeType.ALL) + private List imgs = new ArrayList<>(); } diff --git a/src/main/java/com/readyvery/readyverydemo/domain/StoreImg.java b/src/main/java/com/readyvery/readyverydemo/domain/StoreImg.java new file mode 100644 index 0000000..d4c0a79 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/domain/StoreImg.java @@ -0,0 +1,36 @@ +package com.readyvery.readyverydemo.domain; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Entity +@Table(name = "STORES_IMG") +@AllArgsConstructor +@Slf4j +public class StoreImg { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "store_img_idx") + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "store_idx") + private Store store; + + private String imgUrl; +} diff --git a/src/main/java/com/readyvery/readyverydemo/domain/repository/StoreRepository.java b/src/main/java/com/readyvery/readyverydemo/domain/repository/StoreRepository.java new file mode 100644 index 0000000..72c47f4 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/domain/repository/StoreRepository.java @@ -0,0 +1,9 @@ +package com.readyvery.readyverydemo.domain.repository; + +import org.springframework.data.jpa.repository.JpaRepository; + +import com.readyvery.readyverydemo.domain.Store; + +public interface StoreRepository extends JpaRepository { + +} diff --git a/src/main/java/com/readyvery/readyverydemo/global/exception/BusinessLogicException.java b/src/main/java/com/readyvery/readyverydemo/global/exception/BusinessLogicException.java new file mode 100644 index 0000000..98a823d --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/global/exception/BusinessLogicException.java @@ -0,0 +1,13 @@ +package com.readyvery.readyverydemo.global.exception; + +import lombok.Getter; + +public class BusinessLogicException extends RuntimeException { + @Getter + private ExceptionCode exceptionCode; + + public BusinessLogicException(ExceptionCode exceptionCode) { + super(exceptionCode.getMessage()); + this.exceptionCode = exceptionCode; + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/global/exception/ErrorResponse.java b/src/main/java/com/readyvery/readyverydemo/global/exception/ErrorResponse.java new file mode 100644 index 0000000..54053d4 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/global/exception/ErrorResponse.java @@ -0,0 +1,22 @@ +package com.readyvery.readyverydemo.global.exception; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +public class ErrorResponse { + // 비즈니스로직 예외: 지정된 Code로 생성할 경우 + public static ErrorResponse.Default of(ExceptionCode exceptionCode) { + return new ErrorResponse.Default(exceptionCode.getStatus(), exceptionCode.getMessage()); + } + + @Getter + @AllArgsConstructor + @NoArgsConstructor(access = AccessLevel.PROTECTED) + public static class Default { + private Integer status; + private String message; + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/global/exception/ExceptionCode.java b/src/main/java/com/readyvery/readyverydemo/global/exception/ExceptionCode.java new file mode 100644 index 0000000..9ecafa4 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/global/exception/ExceptionCode.java @@ -0,0 +1,16 @@ +package com.readyvery.readyverydemo.global.exception; + +import lombok.Getter; + +@Getter +public enum ExceptionCode { + STORE_NOT_FOUND(404, "Store does not exists."); + + private int status; + private String message; + + ExceptionCode(int status, String message) { + this.status = status; + this.message = message; + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/global/exception/GlobalExceptionAdvice.java b/src/main/java/com/readyvery/readyverydemo/global/exception/GlobalExceptionAdvice.java new file mode 100644 index 0000000..dd98ee0 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/global/exception/GlobalExceptionAdvice.java @@ -0,0 +1,15 @@ +package com.readyvery.readyverydemo.global.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 GlobalExceptionAdvice { + @ExceptionHandler(BusinessLogicException.class) + public ResponseEntity handleException(BusinessLogicException exception) { + final ErrorResponse.Default response = ErrorResponse.of(exception.getExceptionCode()); + return new ResponseEntity<>(response, HttpStatus.valueOf(response.getStatus())); + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/security/config/SpringSecurityConfig.java b/src/main/java/com/readyvery/readyverydemo/security/config/SpringSecurityConfig.java index da1597d..064dc7a 100644 --- a/src/main/java/com/readyvery/readyverydemo/security/config/SpringSecurityConfig.java +++ b/src/main/java/com/readyvery/readyverydemo/security/config/SpringSecurityConfig.java @@ -1,7 +1,5 @@ package com.readyvery.readyverydemo.security.config; -import static org.springframework.security.config.Customizer.*; - import java.util.Arrays; import org.springframework.boot.autoconfigure.security.servlet.PathRequest; @@ -57,7 +55,8 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers( "/jwt-test", "/oauth2/**", - "/login" + "/login", + "/api/v1/store/**" ).permitAll() // 해당 요청은 인증이 필요함 .anyRequest().authenticated() // 위를 제외한 나머지는 모두 허용 ) diff --git a/src/main/java/com/readyvery/readyverydemo/src/store/StoreController.java b/src/main/java/com/readyvery/readyverydemo/src/store/StoreController.java new file mode 100644 index 0000000..49bfa64 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/src/store/StoreController.java @@ -0,0 +1,25 @@ +package com.readyvery.readyverydemo.src.store; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import com.readyvery.readyverydemo.src.store.dto.StoreDetailRes; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/store") +public class StoreController { + private final StoreService storeService; + + @GetMapping("/{storeId}") + public ResponseEntity getStoreDetail(@PathVariable("storeId") Long storeId) { + StoreDetailRes storeDetailRes = storeService.getStoreDetail(storeId); + return new ResponseEntity<>(storeDetailRes, HttpStatus.OK); + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/src/store/StoreService.java b/src/main/java/com/readyvery/readyverydemo/src/store/StoreService.java new file mode 100644 index 0000000..2058515 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/src/store/StoreService.java @@ -0,0 +1,7 @@ +package com.readyvery.readyverydemo.src.store; + +import com.readyvery.readyverydemo.src.store.dto.StoreDetailRes; + +public interface StoreService { + StoreDetailRes getStoreDetail(Long storeId); +} diff --git a/src/main/java/com/readyvery/readyverydemo/src/store/StoreServiceImpl.java b/src/main/java/com/readyvery/readyverydemo/src/store/StoreServiceImpl.java new file mode 100644 index 0000000..b428c95 --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/src/store/StoreServiceImpl.java @@ -0,0 +1,26 @@ +package com.readyvery.readyverydemo.src.store; + +import org.springframework.stereotype.Service; + +import com.readyvery.readyverydemo.domain.Store; +import com.readyvery.readyverydemo.domain.repository.StoreRepository; +import com.readyvery.readyverydemo.global.exception.BusinessLogicException; +import com.readyvery.readyverydemo.global.exception.ExceptionCode; +import com.readyvery.readyverydemo.src.store.dto.StoreDetailRes; +import com.readyvery.readyverydemo.src.store.dto.StoreMapper; + +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class StoreServiceImpl implements StoreService { + private final StoreRepository storeRepository; + private final StoreMapper storeMapper; + + @Override + public StoreDetailRes getStoreDetail(Long storeId) { + Store store = storeRepository.findById(storeId) + .orElseThrow(() -> new BusinessLogicException(ExceptionCode.STORE_NOT_FOUND)); + return storeMapper.storeToStoreDetailRes(store); + } +} diff --git a/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreDetailRes.java b/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreDetailRes.java new file mode 100644 index 0000000..583620c --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreDetailRes.java @@ -0,0 +1,16 @@ +package com.readyvery.readyverydemo.src.store.dto; + +import java.util.List; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class StoreDetailRes { + private List imgs; + private String name; + private String phone; + private String address; + private String openTime; +} diff --git a/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreMapper.java b/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreMapper.java new file mode 100644 index 0000000..d364f4c --- /dev/null +++ b/src/main/java/com/readyvery/readyverydemo/src/store/dto/StoreMapper.java @@ -0,0 +1,19 @@ +package com.readyvery.readyverydemo.src.store.dto; + +import org.springframework.stereotype.Component; + +import com.readyvery.readyverydemo.domain.Store; +import com.readyvery.readyverydemo.domain.StoreImg; + +@Component +public class StoreMapper { + public StoreDetailRes storeToStoreDetailRes(Store store) { + return StoreDetailRes.builder() + .imgs(store.getImgs().stream().map(StoreImg::getImgUrl).toList()) + .name(store.getName()) + .phone(store.getPhone()) + .address(store.getAddress()) + .openTime(store.getTime()) + .build(); + } +}