Skip to content

Commit

Permalink
Merge pull request #21 from SWM-WeLike2Coding/feat/userInterest
Browse files Browse the repository at this point in the history
�feat: 사용자의 관심 상품 등록 조회 삭제 기능 개발
  • Loading branch information
kjungw1025 authored Aug 1, 2024
2 parents ef20502 + f4edac1 commit 86abea7
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 2 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ dependencies {
// spring cloud
implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
implementation 'org.springframework.cloud:spring-cloud-starter-openfeign'
implementation 'org.springframework.cloud:spring-cloud-starter-circuitbreaker-resilience4j'

// lombok
compileOnly 'org.projectlombok:lombok'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package com.wl2c.elswhereuserservice.client.product.api;

import com.wl2c.elswhereuserservice.client.product.dto.request.RequestProductIdListDto;
import com.wl2c.elswhereuserservice.client.product.dto.response.ResponseSingleProductDto;
import com.wl2c.elswhereuserservice.client.product.dto.response.ResponseSummarizedProductDto;
import jakarta.validation.Valid;
import org.springframework.cloud.openfeign.FeignClient;
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;

import java.util.List;

@FeignClient(name = "product-service")
public interface ProductServiceClient {

@GetMapping("/product/{productId}")
ResponseSingleProductDto getProduct(@PathVariable Long productId);

@PostMapping("/product/list")
List<ResponseSummarizedProductDto> listByProductIds(@Valid @RequestBody RequestProductIdListDto requestProductIdListDto);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.wl2c.elswhereuserservice.client.product.dto.request;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.util.List;

@Getter
public class RequestProductIdListDto {

@Schema(description = "상품 id 리스트", example = "[3, 6, 9, 12]")
private final List<Long> productIdList;

@JsonCreator
public RequestProductIdListDto(@JsonProperty("productIdList") List<Long> productIdList) {
this.productIdList = productIdList;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.wl2c.elswhereuserservice.client.product.dto.response;

import com.wl2c.elswhereuserservice.client.product.ProductType;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;

import java.math.BigDecimal;
import java.time.LocalDate;

@Getter
@Builder
public class ResponseSummarizedProductDto {
@Schema(description = "상품 id", example = "1")
private final Long id;

@Schema(description = "발행 회사", example = "oo투자증권")
private final String issuer;

@Schema(description = "상품명", example = "oo투자증권 99999")
private final String name;

@Schema(description = "상품 유형", example = "STEP_DOWN or LIZARD or MONTHLY_PAYMENT or ETC")
private final ProductType productType;

@Schema(description = "기초자산", example = "KOSPI200 Index / HSCEI Index / S&P500 Index")
private final String equities;

@Schema(description = "수익률", example = "20.55")
private final BigDecimal yieldIfConditionsMet;

@Schema(description = "낙인 값", example = "45, 낙인 값이 없을 시 null return")
private final Integer knockIn;

@Schema(description = "청약 시작일", example = "2024-06-14")
private final LocalDate subscriptionStartDate;

@Schema(description = "청약 마감일", example = "2024-06-21")
private final LocalDate subscriptionEndDate;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package com.wl2c.elswhereuserservice.domain.user.controller;

import com.wl2c.elswhereuserservice.client.product.dto.response.ResponseSummarizedProductDto;
import com.wl2c.elswhereuserservice.domain.user.model.dto.request.RequestCreateInterestDto;
import com.wl2c.elswhereuserservice.domain.user.model.dto.response.ResponseUserInterestDto;
import com.wl2c.elswhereuserservice.domain.user.service.UserInterestService;
import com.wl2c.elswhereuserservice.global.model.dto.ResponseIdDto;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;

import java.util.List;

import static java.lang.Long.parseLong;

@Tag(name = "사용자의 관심 상품", description = "사용자의 관심 상품 관련 api")
@RestController
@RequestMapping("/v1/interest")
@RequiredArgsConstructor
public class UserInterestController {

private final UserInterestService userInterestService;

/**
* 관심 상품 등록
*
* @param dto 등록하고자 하는 상품 id
* @return 관심 상품 id
*/
@PostMapping
public ResponseIdDto create(HttpServletRequest request,
@Valid @RequestBody RequestCreateInterestDto dto) {
return userInterestService.create(parseLong(request.getHeader("requestId")), dto);
}

/**
* 사용자의 관심 상품 리스트 조회
*
* @return 사용자가 등록한 관심 상품 리스트
*/
@GetMapping
public List<ResponseUserInterestDto> read(HttpServletRequest request) {
return userInterestService.read(parseLong(request.getHeader("requestId")));
}

/**
* 특정 관심 상품 삭제
*
* @param id 삭제할 관심 상품 id
*/
@DeleteMapping("/{id}")
public void delete(HttpServletRequest request,
@PathVariable Long id) {
userInterestService.delete(parseLong(request.getHeader("requestId")), id);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.wl2c.elswhereuserservice.domain.user.exception;

import com.wl2c.elswhereuserservice.global.exception.LocalizedMessageException;
import org.springframework.http.HttpStatus;

public class AlreadyInterestException extends LocalizedMessageException {
public AlreadyInterestException() {
super(HttpStatus.BAD_REQUEST, "already.interest");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.wl2c.elswhereuserservice.domain.user.exception;

import com.wl2c.elswhereuserservice.global.exception.LocalizedMessageException;
import org.springframework.http.HttpStatus;

public class InterestNotFoundException extends LocalizedMessageException {
public InterestNotFoundException() { super(HttpStatus.NOT_FOUND, "notfound.interest-product"); }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package com.wl2c.elswhereuserservice.domain.user.model.dto.request;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Getter;

import java.util.List;

@Getter
public class RequestCreateInterestDto {

@Schema(description = "상품 id", example = "3")
private final Long productId;

@JsonCreator
public RequestCreateInterestDto(@JsonProperty("productId") Long productId) {
this.productId = productId;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.wl2c.elswhereuserservice.domain.user.model.dto.response;

import com.wl2c.elswhereuserservice.client.product.ProductType;
import com.wl2c.elswhereuserservice.client.product.dto.response.ResponseSummarizedProductDto;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Getter;
import lombok.NonNull;

import java.math.BigDecimal;
import java.time.LocalDate;

@Getter
public class ResponseUserInterestDto {

@Schema(description = "사용자 관심 상품 id", example = "1")
private final Long interestId;

@Schema(description = "상품 id", example = "3")
private final Long productId;

@Schema(description = "발행 회사", example = "oo투자증권")
private final String issuer;

@Schema(description = "상품명", example = "oo투자증권 99999")
private final String name;

@Schema(description = "상품 유형", example = "STEP_DOWN or LIZARD or MONTHLY_PAYMENT or ETC")
private final ProductType productType;

@Schema(description = "기초자산", example = "KOSPI200 Index / HSCEI Index / S&P500 Index")
private final String equities;

@Schema(description = "수익률", example = "20.55")
private final BigDecimal yieldIfConditionsMet;

@Schema(description = "낙인 값", example = "45, 낙인 값이 없을 시 null return")
private final Integer knockIn;

@Schema(description = "청약 시작일", example = "2024-06-14")
private final LocalDate subscriptionStartDate;

@Schema(description = "청약 마감일", example = "2024-06-21")
private final LocalDate subscriptionEndDate;

public ResponseUserInterestDto(@NonNull Long interestId,
@NonNull ResponseSummarizedProductDto responseSummarizedProductDto) {
this.interestId = interestId;
this.productId = responseSummarizedProductDto.getId();
this.issuer = responseSummarizedProductDto.getIssuer();
this.name = responseSummarizedProductDto.getName();
this.productType = responseSummarizedProductDto.getProductType();
this.equities = responseSummarizedProductDto.getEquities();
this.yieldIfConditionsMet = responseSummarizedProductDto.getYieldIfConditionsMet();
this.knockIn = responseSummarizedProductDto.getKnockIn();
this.subscriptionStartDate = responseSummarizedProductDto.getSubscriptionStartDate();
this.subscriptionEndDate = responseSummarizedProductDto.getSubscriptionEndDate();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.wl2c.elswhereuserservice.domain.user.model.entity;

import com.wl2c.elswhereuserservice.domain.user.model.AlarmStatus;
import com.wl2c.elswhereuserservice.global.base.BaseEntity;
import jakarta.persistence.*;
import jakarta.validation.constraints.NotNull;
import lombok.*;

import static jakarta.persistence.EnumType.STRING;

@Entity
@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Interest extends BaseEntity {

@Id
@GeneratedValue
@Column(name = "interest_id")
private Long id;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "user_id")
private User user;

@NotNull
private Long productId;

@Enumerated(STRING)
private AlarmStatus subscriptionEndDateAlarm;

@Builder
public Interest(User user,
@NonNull Long productId) {
this.user = user;
this.productId = productId;
this.subscriptionEndDateAlarm = AlarmStatus.ACTIVE;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,9 @@ public class User extends BaseEntity {
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Holding> holdingList = new ArrayList<>();

@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Interest> interestList = new ArrayList<>();

@Builder
private User (@NonNull String socialId,
@NonNull SocialType socialType,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.wl2c.elswhereuserservice.domain.user.repository;

import com.wl2c.elswhereuserservice.domain.user.model.entity.Interest;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.util.List;
import java.util.Optional;

public interface UserInterestRepository extends JpaRepository<Interest, Long> {

@Modifying(clearAutomatically = true)
@Query("delete from Interest i " +
"where i.id = :id and i.user.id = :userId ")
void deleteInterest(@Param("userId") Long userId,
@Param("id") Long id);

@Query("select i from Interest i where i.user.id = :userId ")
List<Interest> findAllByUserId(@Param("userId") Long userId);

@Query("select i from Interest i " +
"where i.user.id = :userId " +
"and i.productId = :productId ")
Optional<Interest> findByUserIdAndProductId(@Param("userId") Long userId,
@Param("productId") Long productId);
}
Loading

0 comments on commit 86abea7

Please sign in to comment.