Skip to content
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

[feat] 구매자는 매장 리스트를 조회할 수 있다 #81

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
62ef391
[fix] Store : StoreCategory = N : 1 이므로 OneToOne에서 ManyToOne으로 연관관계 수정
Hyeon-Uk Aug 15, 2024
b731ca9
[build] QueryDsl 5.0 버전 설정
Hyeon-Uk Aug 15, 2024
20b1575
[docs] .gitIgnore에 QEntity가 포함된 /src/main/generated 폴더 하위를 추가
Hyeon-Uk Aug 15, 2024
b5f5a0c
[feat] StoreCategory 도메인 엔티티에 getter 추가
Hyeon-Uk Aug 15, 2024
4662c3a
[feat] Client에게 전달될 가게 정보의 리스트에 대한 ResponseDto 생성
Hyeon-Uk Aug 15, 2024
4bc1e0a
[test] Client에게 전달될 가게 정보의 리스트에 대한 ResponseDto 테스트코드 작성
Hyeon-Uk Aug 15, 2024
2394367
[feat] 클라이언트가 볼 수 있는 Store의 정보를 모두 불러오는 findAllStoreList 구현
Hyeon-Uk Aug 15, 2024
8f1cedc
[test] 클라이언트가 볼 수 있는 Store의 정보를 모두 불러오는 findAllStoreList 테스트 구현
Hyeon-Uk Aug 15, 2024
5398a33
[feat] 클라이언트가 볼 수 있는 Store의 정보를 모두 불러오는 getStoreInfos 메서드를 StoreApiCo…
Hyeon-Uk Aug 15, 2024
9efc3a1
[test] 클라이언트가 볼 수 있는 Store의 정보를 모두 불러오는 getStoreInfos 메서드 테스트
Hyeon-Uk Aug 15, 2024
c77bcb0
[fix] StoreDao 관련 API 수정
Hyeon-Uk Aug 16, 2024
0706db9
[refactor] JPAQueryFactory를 BeanContainer로 생성 후 관리하도록 변경
Hyeon-Uk Aug 16, 2024
54f0b0c
[chore] 매장의 리스트를 조회해오는 메서드에 TODO 작성
Hyeon-Uk Aug 16, 2024
0bf48bc
[chore] 매장의 리스트를 조회한 결과를 반환하는 DTO 이름을 StoreInfoResponse -> StoreInfoL…
Hyeon-Uk Aug 16, 2024
d115fd4
[feat] Paging 처리를 위해 StoreInfoList의 requestDto를 size와 page를 포함하여 생성
Hyeon-Uk Aug 16, 2024
65e6012
[fix] PageRequest에서 size는 DefaultSize만 사용하도록 수정
Hyeon-Uk Aug 16, 2024
5304ae9
[feat] Store정보의 리스트를 반환할 때 page와 limit을 이용해서 paging처리
Hyeon-Uk Aug 16, 2024
82763fe
[feat] StoreDummies를 생성하는 StoreDummiesFixture 구현
Hyeon-Uk Aug 16, 2024
6d5b039
[refactor] StoreDao에 StoreDummiesFixture 적용 및 기존 리스트 검증 방식을 페이지 검증 방식…
Hyeon-Uk Aug 16, 2024
1c875f8
[feat] 쿼리 파라미터에서 쉽게 페이징 및 필터링 조건을 DTO로 받기 위한 ArgumentResolver 구현 및 등록
Hyeon-Uk Aug 16, 2024
255605f
[feat] StoreApiController에서 기존 리스트를 전부 불러오는 로직에서 페이징 처리된 리스트를 반환하도록 구현
Hyeon-Uk Aug 16, 2024
ca19dc4
[test] StoreApiController에서 기존 리스트를 전부 불러오는 로직에서 페이징 처리된 리스트를 반환하는 테스…
Hyeon-Uk Aug 16, 2024
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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -194,4 +194,5 @@ gradle-app.setting
# Java heap dump
*.hprof

# End of https://www.toptal.com/developers/gitignore/api/gradle,java,intellij
# End of https://www.toptal.com/developers/gitignore/api/gradle,java,intellij
/src/main/generated/
71 changes: 49 additions & 22 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,42 +1,69 @@
plugins {
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
id 'java'
id 'org.springframework.boot' version '3.3.2'
id 'io.spring.dependency-management' version '1.1.6'
}

group = 'camp.woowak'
version = '0.0.1-SNAPSHOT'

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

configurations {
compileOnly {
extendsFrom annotationProcessor
}
compileOnly {
extendsFrom annotationProcessor
}
}

repositories {
mavenCentral()
mavenCentral()
}

dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.springframework.boot:spring-boot-starter-web'
compileOnly 'org.projectlombok:lombok'
developmentOnly 'org.springframework.boot:spring-boot-devtools'
runtimeOnly 'com.h2database:h2'
runtimeOnly 'com.mysql:mysql-connector-j'
annotationProcessor 'org.projectlombok:lombok'
testImplementation 'org.springframework.boot:spring-boot-starter-test'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'

//QueryDsl
// QueryDsl
implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta'
annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta"
annotationProcessor "jakarta.annotation:jakarta.annotation-api"
annotationProcessor "jakarta.persistence:jakarta.persistence-api"
}

tasks.named('test') {
useJUnitPlatform()
useJUnitPlatform()
}

// Querydsl 설정부
def generated = 'src/main/generated'

// querydsl QClass 생성 위치
tasks.withType(JavaCompile) {
options.generatedSourceOutputDirectory = file(generated)
}

task cleanGenerated(type: Delete) {
delete generated
}

clean.dependsOn cleanGenerated
compileJava.dependsOn clean

// java source set 에 querydsl QClass 위치 추가
sourceSets {
main.java.srcDirs += "$projectDir/build/generated"
}
3 changes: 1 addition & 2 deletions src/main/java/camp/woowak/lab/store/domain/Store.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.OneToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -32,7 +31,7 @@ public class Store {
@JoinColumn(name = "vendor_id", nullable = false)
private Vendor owner;

@OneToOne
@ManyToOne
@JoinColumn(name = "store_category_id", nullable = false)
private StoreCategory storeCategory;

Expand Down
2 changes: 2 additions & 0 deletions src/main/java/camp/woowak/lab/store/domain/StoreCategory.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
public class StoreCategory {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.List;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
Expand All @@ -15,12 +16,16 @@
import camp.woowak.lab.store.service.command.StoreRegistrationCommand;
import camp.woowak.lab.web.authentication.LoginVendor;
import camp.woowak.lab.web.authentication.annotation.AuthenticationPrincipal;
import camp.woowak.lab.web.dao.store.StoreDao;
import camp.woowak.lab.web.dto.request.store.MenuCategoryRegistrationRequest;
import camp.woowak.lab.web.dto.request.store.StoreInfoListRequest;
import camp.woowak.lab.web.dto.request.store.StoreMenuRegistrationRequest;
import camp.woowak.lab.web.dto.request.store.StoreRegistrationRequest;
import camp.woowak.lab.web.dto.response.store.MenuCategoryRegistrationResponse;
import camp.woowak.lab.web.dto.response.store.StoreInfoListResponse;
import camp.woowak.lab.web.dto.response.store.StoreMenuRegistrationResponse;
import camp.woowak.lab.web.dto.response.store.StoreRegistrationResponse;
import camp.woowak.lab.web.resolver.store.annotation.StorePFS;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;

Expand All @@ -31,6 +36,13 @@ public class StoreApiController {
private final StoreRegistrationService storeRegistrationService;
private final StoreMenuRegistrationService storeMenuRegistrationService;
private final MenuCategoryRegistrationService menuCategoryRegistrationService;
private final StoreDao storeDao;

@GetMapping("/stores")
public StoreInfoListResponse getStoreInfos(@StorePFS StoreInfoListRequest request
) {
return storeDao.findAllStoreList(request);
}

@PostMapping("/stores")
public StoreRegistrationResponse storeRegistration(@AuthenticationPrincipal final LoginVendor loginVendor,
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/camp/woowak/lab/web/config/QuerydslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package camp.woowak.lab.web.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.querydsl.jpa.impl.JPAQueryFactory;

import jakarta.persistence.EntityManager;

@Configuration
public class QuerydslConfig {
@Bean
public JPAQueryFactory jpaQueryFactory(EntityManager entityManager) {
return new JPAQueryFactory(entityManager);
}
}
5 changes: 4 additions & 1 deletion src/main/java/camp/woowak/lab/web/config/WebConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,19 @@

import camp.woowak.lab.web.resolver.session.SessionCustomerArgumentResolver;
import camp.woowak.lab.web.resolver.session.SessionVendorArgumentResolver;
import camp.woowak.lab.web.resolver.store.StorePageableFilterSortArgumentResolver;
import lombok.RequiredArgsConstructor;

@Configuration
@RequiredArgsConstructor
public class WebConfig implements WebMvcConfigurer {
private final SessionCustomerArgumentResolver sessionCustomerArgumentResolver;
private final SessionVendorArgumentResolver sessionVendorArgumentResolver;
private final StorePageableFilterSortArgumentResolver storePageableFilterSortArgumentResolver;

@Override
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.addAll(List.of(sessionCustomerArgumentResolver, sessionVendorArgumentResolver));
resolvers.addAll(List.of(sessionCustomerArgumentResolver, sessionVendorArgumentResolver,
storePageableFilterSortArgumentResolver));
}
}
42 changes: 42 additions & 0 deletions src/main/java/camp/woowak/lab/web/dao/store/StoreDao.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package camp.woowak.lab.web.dao.store;

import java.util.List;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.querydsl.jpa.impl.JPAQueryFactory;

import camp.woowak.lab.store.domain.QStore;
import camp.woowak.lab.store.domain.Store;
import camp.woowak.lab.web.dto.request.store.StoreInfoListRequest;
import camp.woowak.lab.web.dto.response.store.StoreInfoListResponse;

@Repository
@Transactional(readOnly = true)
public class StoreDao {
private final JPAQueryFactory qf;

public StoreDao(JPAQueryFactory qf) {
this.qf = qf;
}

/**
* TODO 페이지별 매장 리스트를 조회할 수 있다.
* TODO 주문이 많은 순으로 정렬할 수 있다.
* TODO 최소 주문 가격순으로 정렬할 수 있다.
* TODO 최소 주문 가격으로 필터링할 수 있다.
* TODO 매장의 카테고리로 필터링할 수 잇다.
*/
public StoreInfoListResponse findAllStoreList(StoreInfoListRequest request) {
QStore store = QStore.store;

List<Store> fetchResult = qf.select(store)
.from(store)
.offset(request.getPage()*request.getSize())
.limit(request.getSize())
.fetch();

return StoreInfoListResponse.of(fetchResult);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package camp.woowak.lab.web.dto.request.store;

import lombok.Getter;

@Getter
public class StoreInfoListRequest {
public static final int DEFAULT_PAGE_SIZE = 20;
public static final int DEFAULT_PAGE_NUMBER = 0;

private final int size;//서버에서 사이즈는 고정하기로
private final int page;

public StoreInfoListRequest(int page) {
this.page = page;
this.size = DEFAULT_PAGE_SIZE;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package camp.woowak.lab.web.dto.request.store;

public final class StoreInfoListRequestConst {
public static final String PAGE_KEY = "page";

private StoreInfoListRequestConst() {
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package camp.woowak.lab.web.dto.response.store;

import java.util.List;

import camp.woowak.lab.store.domain.Store;
import lombok.Getter;

@Getter
public class StoreInfoListResponse {
private List<InfoResponse> stores;

private StoreInfoListResponse(List<InfoResponse> stores) {
this.stores = stores;
}

public static StoreInfoListResponse of(List<Store> stores) {
List<InfoResponse> storeInfos = stores.stream()
.map(InfoResponse::of)
.toList();

return new StoreInfoListResponse(storeInfos);
}

@Getter
public static class InfoResponse {
private final Long storeId;
private final boolean open;
private final String name;
private final String category;
private final int minOrderPrice;

private InfoResponse(Long storeId, boolean open, String name, String category, int minOrderPrice) {
this.storeId = storeId;
this.open = open;
this.name = name;
this.category = category;
this.minOrderPrice = minOrderPrice;
}

private static InfoResponse of(Store store) {
return new InfoResponse(store.getId(), store.isOpen(), store.getName(), store.getStoreCategory().getName(),
store.getMinOrderPrice());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package camp.woowak.lab.web.resolver.store;

import org.springframework.core.MethodParameter;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;

import camp.woowak.lab.web.dto.request.store.StoreInfoListRequest;
import camp.woowak.lab.web.dto.request.store.StoreInfoListRequestConst;
import camp.woowak.lab.web.resolver.store.annotation.StorePFS;
import lombok.extern.slf4j.Slf4j;

@Component
@Slf4j
public class StorePageableFilterSortArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
return parameter.hasParameterAnnotation(StorePFS.class)
&& parameter.getClass().isAssignableFrom(StoreInfoListRequest.class);
}

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
String pageParameter = webRequest.getParameter(StoreInfoListRequestConst.PAGE_KEY);
int page = parsePageNumber(pageParameter);

return new StoreInfoListRequest(page);
}

private int parsePageNumber(String str) {
try {
return Integer.parseInt(str);
} catch (NumberFormatException e) {
return StoreInfoListRequest.DEFAULT_PAGE_NUMBER;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package camp.woowak.lab.web.resolver.store.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.PARAMETER)
public @interface StorePFS {
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import camp.woowak.lab.web.authentication.LoginVendor;
import camp.woowak.lab.web.authentication.NoOpPasswordEncoder;
import camp.woowak.lab.web.authentication.PasswordEncoder;
import camp.woowak.lab.web.dao.store.StoreDao;
import camp.woowak.lab.web.dto.request.store.MenuCategoryRegistrationRequest;
import camp.woowak.lab.web.dto.request.store.StoreRegistrationRequest;
import camp.woowak.lab.web.resolver.session.SessionConst;
Expand All @@ -65,6 +66,9 @@ class StoreApiControllerTest {
@MockBean
private VendorRepository vendorRepository;

@MockBean
private StoreDao storeDao;

@MockBean
private SessionVendorArgumentResolver sessionVendorArgumentResolver;

Expand Down
Loading