Skip to content
This repository has been archived by the owner on Oct 20, 2024. It is now read-only.

Commit

Permalink
Merge pull request #37 from FinFellows/develop
Browse files Browse the repository at this point in the history
[FEAT]: 예금 조회 API (조건 별 조회 가능) 구현
  • Loading branch information
sejineer authored Jan 2, 2024
2 parents 02bcd4d + 25eec76 commit b654332
Show file tree
Hide file tree
Showing 15 changed files with 286 additions and 5 deletions.
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ dependencies {
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5'
runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5'

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

annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
annotationProcessor 'org.projectlombok:lombok'

Expand All @@ -50,4 +56,4 @@ dependencies {

tasks.named('test') {
useJUnitPlatform()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.finfellows.domain.product.application;

import com.finfellows.domain.product.dto.condition.DepositSearchCondition;
import com.finfellows.domain.product.dto.response.SearchDepositRes;
import com.finfellows.global.config.security.token.UserPrincipal;
import com.finfellows.global.payload.PagedResponse;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface FinancialProductService {

PagedResponse<SearchDepositRes> findDepositProducts(UserPrincipal userPrincipal, DepositSearchCondition depositSearchCondition, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.finfellows.domain.product.application;

import com.finfellows.domain.product.domain.repository.FinancialProductRepository;
import com.finfellows.domain.product.dto.condition.DepositSearchCondition;
import com.finfellows.domain.product.dto.response.SearchDepositRes;
import com.finfellows.global.config.security.token.UserPrincipal;
import com.finfellows.global.payload.PagedResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@RequiredArgsConstructor
@Service
@Transactional(readOnly = true)
public class FinancialProductServiceImpl implements FinancialProductService {

private final FinancialProductRepository financialProductRepository;

@Override
public PagedResponse<SearchDepositRes> findDepositProducts(UserPrincipal userPrincipal, DepositSearchCondition depositSearchCondition, Pageable pageable) {
Page<SearchDepositRes> financialProducts = financialProductRepository.findFinancialProducts(depositSearchCondition, pageable);

return new PagedResponse<>(financialProducts);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
@Table(name = "Financial_Product")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Where(clause = "status = 'ACTIVE'")
public class FinancialProduct extends BaseEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
@Table(name = "Financial_Product_Option")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Getter
@Where(clause = "status = 'ACTIVE'")
public class FinancialProductOption extends BaseEntity {

@Id
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.finfellows.domain.product.domain.repository;

import com.finfellows.domain.product.domain.FinancialProduct;
import com.finfellows.domain.product.dto.condition.DepositSearchCondition;
import com.finfellows.domain.product.dto.response.SearchDepositRes;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.List;

public interface FinancialProductQueryDslRepository {

Page<SearchDepositRes> findFinancialProducts(DepositSearchCondition depositSearchCondition, Pageable pageable);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.finfellows.domain.product.domain.repository;

import com.finfellows.domain.product.domain.FinancialProduct;
import com.finfellows.domain.product.domain.FinancialProductType;
import com.finfellows.domain.product.domain.QFinancialProduct;
import com.finfellows.domain.product.domain.QFinancialProductOption;
import com.finfellows.domain.product.dto.condition.DepositSearchCondition;
import com.finfellows.domain.product.dto.response.QSearchDepositRes;
import com.finfellows.domain.product.dto.response.SearchDepositRes;
import com.querydsl.core.QueryResults;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.support.PageableExecutionUtils;
import org.springframework.stereotype.Repository;

import java.util.List;

import static com.finfellows.domain.product.domain.QFinancialProduct.*;
import static com.finfellows.domain.product.domain.QFinancialProductOption.*;

@RequiredArgsConstructor
@Repository
public class FinancialProductQueryDslRepositoryImpl implements FinancialProductQueryDslRepository {

private final JPAQueryFactory queryFactory;

@Override
public Page<SearchDepositRes> findFinancialProducts(DepositSearchCondition depositSearchCondition, Pageable pageable) {
List<SearchDepositRes> results = queryFactory
.select(new QSearchDepositRes(
financialProduct.id,
financialProduct.productName,
financialProduct.companyName,
financialProductOption.maximumPreferredInterestRate,
financialProductOption.interestRate
))
.from(financialProductOption)
.leftJoin(financialProductOption.financialProduct, financialProduct)
.where(
financialProduct.financialProductType.eq(FinancialProductType.DEPOSIT),
typeEq(depositSearchCondition.getType()),
preferentialConditionEq(depositSearchCondition.getPreferentialCondition()),
termEq(depositSearchCondition.getTerm())
)
.orderBy(financialProductOption.maximumPreferredInterestRate.desc())
.offset(pageable.getOffset())
.limit(pageable.getPageSize())
.fetch();

JPAQuery<Long> countQuery = queryFactory
.select(financialProductOption.count())
.from(financialProductOption)
.leftJoin(financialProductOption.financialProduct, financialProduct)
.where(
financialProduct.financialProductType.eq(FinancialProductType.DEPOSIT),
typeEq(depositSearchCondition.getType()),
preferentialConditionEq(depositSearchCondition.getPreferentialCondition()),
termEq(depositSearchCondition.getTerm())
);

// Page 객체 생성
return PageableExecutionUtils.getPage(results, pageable, countQuery::fetchOne);
}

private BooleanExpression termEq(Integer term) {
return term != null ? financialProductOption.savingsTerm.eq(term) : null;
}

private BooleanExpression typeEq(String type) {
return type != null ? financialProductOption.financialProduct.joinWay.contains(type) : null;
}

private BooleanExpression preferentialConditionEq(String preferentialCondition) {
return preferentialCondition != null ? financialProductOption.financialProduct.specialCondition.contains(preferentialCondition) : null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import com.finfellows.domain.product.domain.FinancialProduct;
import org.springframework.data.jpa.repository.JpaRepository;

public interface FinancialProductRepository extends JpaRepository<FinancialProduct, Long> {
import java.util.List;

public interface FinancialProductRepository extends JpaRepository<FinancialProduct, Long>, FinancialProductQueryDslRepository {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.finfellows.domain.product.dto.condition;

import lombok.Data;

@Data
public class DepositSearchCondition {

private Integer term;
private String type;
private String preferentialCondition;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.finfellows.domain.product.dto.response;

import lombok.Data;

@Data
public class SearchDepositPagingRes {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.finfellows.domain.product.dto.response;

import com.querydsl.core.annotations.QueryProjection;
import lombok.Data;

@Data
public class SearchDepositRes {

private Long id;
private String productName;
private String bankName;
private String maxInterestRate;
private String interestRate;

@QueryProjection
public SearchDepositRes(Long id, String productName, String bankName, String maxInterestRate, String interestRate) {
this.id = id;
this.productName = productName;
this.bankName = bankName;
this.maxInterestRate = maxInterestRate;
this.interestRate = interestRate;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.finfellows.domain.product.presentation;

import com.finfellows.domain.product.application.FinancialProductServiceImpl;
import com.finfellows.domain.product.dto.condition.DepositSearchCondition;
import com.finfellows.domain.product.dto.response.SearchDepositRes;
import com.finfellows.global.config.security.token.CurrentUser;
import com.finfellows.global.config.security.token.UserPrincipal;
import com.finfellows.global.payload.ErrorResponse;
import com.finfellows.global.payload.PagedResponse;
import com.finfellows.global.payload.ResponseCustom;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.ArraySchema;
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 org.springframework.data.domain.Pageable;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Tag(name = "FinancialProducts", description = "FinancialProducts API")
@RestController
@RequiredArgsConstructor
@RequestMapping("/financial-products")
public class FinancialProductController {

private final FinancialProductServiceImpl financialProductServiceImpl;

@Operation(summary = "예금 정보 조회", description = "예금 정보를 조건에 따라 조회합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "예금 정보 조회 성공", content = {@Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = SearchDepositRes.class)))}),
@ApiResponse(responseCode = "400", description = "예금 정보 조회 실패", content = {@Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class))}),
})
@GetMapping("/deposit")
public ResponseCustom<PagedResponse<SearchDepositRes>> findDepositProducts(
@Parameter(description = "AccessToken 을 입력해주세요.", required = true) @CurrentUser UserPrincipal userPrincipal,
@ModelAttribute DepositSearchCondition depositSearchCondition,
Pageable pageable
) {
return ResponseCustom.OK(financialProductServiceImpl.findDepositProducts(userPrincipal, depositSearchCondition, pageable));
}

}
20 changes: 20 additions & 0 deletions src/main/java/com/finfellows/global/config/QueryDslConfig.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.finfellows.global.config;

import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class QueryDslConfig {

@PersistenceContext
private EntityManager entityManager;

@Bean
public JPAQueryFactory queryFactory() {
return new JPAQueryFactory(entityManager);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
.permitAll()
.requestMatchers("/login/**", "/auth/**", "/oauth2/**")
.permitAll()
.requestMatchers("/blog/**")
.requestMatchers("/blog/**", "/financial-products/**")
.permitAll()
.anyRequest()
.authenticated());
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/com/finfellows/global/payload/PagedResponse.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.finfellows.global.payload;

import lombok.Data;
import org.springframework.data.domain.Page;

import java.util.List;

@Data
public class PagedResponse<T> {

private int pageNumber;
private int totalPages;
private List<T> content;

public PagedResponse(Page<T> page) {
this.pageNumber = page.getNumber();
this.totalPages = page.getTotalPages();
this.content = page.getContent();
}

}

0 comments on commit b654332

Please sign in to comment.