Skip to content

Commit

Permalink
[refactor] 회원 엔티티 클래스 수정 (#484)
Browse files Browse the repository at this point in the history
* refactor: 임베디드 클래스로 분리

* refactor: 정적 팩토리 수정

* fix: MemberProfile 위임 메서드 추가 및 JPQL 오타 수정

* fix: 포트폴리오 배당금 계산 메서드에 LocalDateTimeService 인수 추가

- 목객체 주입위해서

* fix: 테스트 실패 해결

* test: 테스트 추가

* refactor: oauthMember 메서드 매개변수 줄임

* refactor: 정적 팩토리 추가

* refactor: 기존 로컬 회원 정적 팩토리 메서드 제거

* refactor: 기존 로컬 회원 정적 팩토리 제거

* refactor: profileUrl을 MemberProfile로 이동

* refactor: 메서드 타입을 void로 변경

* refactor: MemberRole 가변인수 메서드로 변경

* test: addMemberRole 메서드 테스트 추가

* refactor: Member와 NotificationPreference 연관관계 편의 메서드 개선

* refactor: Member, MemberRole간에 연관관계 편의 메서드 구현

* rename: 메서드명 변경

* feat: 연관관계 편의 메서드 구현

* feat: toString 재정의

* style: roleSet을 roles로 변경

* test: add test

* style: 메서드명 변경
  • Loading branch information
yonghwankim-dev authored Oct 2, 2024
1 parent 2367a0a commit 234a6aa
Show file tree
Hide file tree
Showing 44 changed files with 551 additions and 219 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import co.fineants.api.domain.common.money.Percentage;
import co.fineants.api.domain.gainhistory.domain.entity.PortfolioGainHistory;
import co.fineants.api.domain.portfolio.domain.entity.Portfolio;
import co.fineants.api.global.common.time.LocalDateTimeService;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down Expand Up @@ -41,7 +42,8 @@ public class PortfolioDetailResponse {
private Boolean targetGainNotify;
private Boolean maxLossNotify;

public static PortfolioDetailResponse from(Portfolio portfolio, PortfolioGainHistory history) {
public static PortfolioDetailResponse from(Portfolio portfolio, PortfolioGainHistory history,
LocalDateTimeService localDateTimeService) {
Bank bank = Bank.getInstance();
Currency to = Currency.KRW;
return PortfolioDetailResponse.builder()
Expand All @@ -60,11 +62,12 @@ public static PortfolioDetailResponse from(Portfolio portfolio, PortfolioGainHis
.dailyGain(portfolio.calculateDailyGain(history).reduce(bank, to))
.dailyGainRate(portfolio.calculateDailyGainRate(history).toPercentage(Bank.getInstance(), to))
.balance(portfolio.calculateBalance().reduce(bank, to))
.annualDividend(portfolio.calculateAnnualDividend().reduce(bank, to))
.annualDividend(portfolio.calculateAnnualDividend(localDateTimeService).reduce(bank, to))
.annualDividendYield(
portfolio.calculateAnnualDividendYield().toPercentage(Bank.getInstance(), to))
portfolio.calculateAnnualDividendYield(localDateTimeService).toPercentage(Bank.getInstance(), to))
.annualInvestmentDividendYield(
portfolio.calculateAnnualInvestmentDividendYield().toPercentage(Bank.getInstance(), to))
portfolio.calculateAnnualInvestmentDividendYield(localDateTimeService)
.toPercentage(Bank.getInstance(), to))
.provisionalLossBalance(Money.zero())
.targetGainNotify(portfolio.getTargetGainIsActive())
.maxLossNotify(portfolio.getMaximumLossIsActive())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import co.fineants.api.domain.gainhistory.domain.entity.PortfolioGainHistory;
import co.fineants.api.domain.holding.domain.entity.PortfolioHolding;
import co.fineants.api.domain.portfolio.domain.entity.Portfolio;
import co.fineants.api.global.common.time.LocalDateTimeService;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
Expand All @@ -22,8 +23,10 @@ public class PortfolioHoldingsResponse {
private List<PortfolioHoldingItem> portfolioHoldings;

public static PortfolioHoldingsResponse of(Portfolio portfolio, PortfolioGainHistory history,
List<PortfolioHolding> portfolioHoldings, Map<String, Money> lastDayClosingPriceMap) {
PortfolioDetailResponse portfolioDetailResponse = PortfolioDetailResponse.from(portfolio, history);
List<PortfolioHolding> portfolioHoldings, Map<String, Money> lastDayClosingPriceMap,
LocalDateTimeService localDateTimeService) {
PortfolioDetailResponse portfolioDetailResponse = PortfolioDetailResponse.from(portfolio, history,
localDateTimeService);
List<PortfolioHoldingItem> portfolioHoldingItems = portfolioHoldings.stream()
.map(portfolioHolding -> PortfolioHoldingItem.from(portfolioHolding,
lastDayClosingPriceMap.getOrDefault(portfolioHolding.getStock().getTickerSymbol(), Money.zero())))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import co.fineants.api.domain.holding.domain.dto.response.PortfolioDetailResponse;
import co.fineants.api.domain.kis.repository.CurrentPriceRedisRepository;
import co.fineants.api.domain.portfolio.domain.entity.Portfolio;
import co.fineants.api.global.common.time.LocalDateTimeService;
import lombok.RequiredArgsConstructor;

@Component
Expand All @@ -18,6 +19,7 @@ public class PortfolioDetailFactory {

private final CurrentPriceRedisRepository manager;
private final PortfolioGainHistoryRepository portfolioGainHistoryRepository;
private final LocalDateTimeService localDateTimeService;

public PortfolioDetailResponse createPortfolioDetailItem(Portfolio portfolio) {
portfolio.applyCurrentPriceAllHoldingsBy(manager);
Expand All @@ -27,7 +29,7 @@ public PortfolioDetailResponse createPortfolioDetailItem(Portfolio portfolio) {
.stream()
.findFirst()
.orElseGet(() -> PortfolioGainHistory.empty(portfolio));
return PortfolioDetailResponse.from(portfolio, history);
return PortfolioDetailResponse.from(portfolio, history, localDateTimeService);
}

public PortfolioDetailRealTimeItem createPortfolioDetailRealTimeItem(Portfolio portfolio) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package co.fineants.api.domain.member.domain.dto.request;

import co.fineants.api.domain.member.domain.entity.Member;
import co.fineants.api.domain.notificationpreference.domain.entity.NotificationPreference;
import jakarta.validation.constraints.NotNull;
import lombok.AccessLevel;
Expand All @@ -24,7 +23,7 @@ public class MemberNotificationPreferenceRequest {
private Boolean targetPriceNotify;
private Long fcmTokenId;

public NotificationPreference toEntity(Member member) {
return NotificationPreference.create(browserNotify, targetGainNotify, maxLossNotify, targetPriceNotify, member);
public NotificationPreference toEntity() {
return NotificationPreference.create(browserNotify, targetGainNotify, maxLossNotify, targetPriceNotify);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.springframework.web.multipart.MultipartFile;

import co.fineants.api.domain.member.domain.entity.Member;
import co.fineants.api.domain.member.domain.entity.MemberProfile;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Builder;
Expand Down Expand Up @@ -40,6 +41,7 @@ public static SignUpServiceRequest of(SignUpRequest request, MultipartFile profi
}

public Member toEntity(String profileUrl, String encodedPassword) {
return Member.localMember(email, nickname, encodedPassword, profileUrl);
MemberProfile profile = MemberProfile.localMemberProfile(email, nickname, encodedPassword, profileUrl);
return Member.localMember(profile);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static OauthMemberResponse from(Member member, MemberNotificationPreferen
member.getId(),
member.getNickname(),
member.getEmail(),
member.getProfileUrl(),
member.getProfileUrl().orElse(null),
member.getProvider(),
response);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public static ProfileResponse from(Member member, NotificationPreference prefere
.id(member.getId())
.nickname(member.getNickname())
.email(member.getEmail())
.profileUrl(member.getProfileUrl())
.profileUrl(member.getProfileUrl().orElse(null))
.provider(member.getProvider())
.notificationPreferences(preference)
.build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static SignUpServiceResponse from(Member member) {
.id(member.getId())
.nickname(member.getNickname())
.email(member.getEmail())
.profileUrl(member.getProfileUrl())
.profileUrl(member.getProfileUrl().orElse(null))
.provider(member.getProvider())
.build();
}
Expand Down
140 changes: 81 additions & 59 deletions src/main/java/co/fineants/api/domain/member/domain/entity/Member.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

Expand All @@ -13,7 +14,7 @@
import co.fineants.api.domain.BaseEntity;
import co.fineants.api.domain.notificationpreference.domain.entity.NotificationPreference;
import jakarta.persistence.CascadeType;
import jakarta.persistence.Column;
import jakarta.persistence.Embedded;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
Expand All @@ -25,96 +26,94 @@
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;

@Getter
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@Entity
@ToString(exclude = {"notificationPreference", "roles"})
@EqualsAndHashCode(of = {"email", "nickname", "provider"}, callSuper = false)
@EqualsAndHashCode(of = {"profile"}, callSuper = false)
public class Member extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String email;
@Column(name = "nickname", unique = true, nullable = false)
private String nickname;
private String provider;
private String password;
private String profileUrl;

@Embedded
private MemberProfile profile;

@OneToOne(fetch = FetchType.LAZY, mappedBy = "member", orphanRemoval = true, cascade = CascadeType.ALL)
private NotificationPreference notificationPreference;

@OneToMany(fetch = FetchType.LAZY, mappedBy = "member", orphanRemoval = true, cascade = CascadeType.ALL)
private Set<MemberRole> roles;
private final Set<MemberRole> roles = new HashSet<>();

private Member(Long id, String email, String nickname, String provider, String password, String profileUrl,
NotificationPreference notificationPreference, Set<MemberRole> roles) {
this.id = id;
this.email = email;
this.nickname = nickname;
this.provider = provider;
this.password = password;
this.profileUrl = profileUrl;
this.notificationPreference = notificationPreference;
this.roles = roles;
private Member(MemberProfile profile) {
this(null, profile);
}

public static Member oauthMember(String email, String nickname, String provider,
String profileUrl) {
return new Member(null, email, nickname, provider, null, profileUrl, null, new HashSet<>());
private Member(Long id, MemberProfile profile) {
this.id = id;
this.profile = profile;
}

public static Member localMember(String email, String nickname, String password) {
return localMember(email, nickname, password, null);
public static Member oauthMember(MemberProfile profile) {
return new Member(profile);
}

public static Member localMember(String email, String nickname, String password, String profileUrl) {
return localMember(null, email, nickname, password, profileUrl);
public static Member localMember(MemberProfile profile) {
return new Member(profile);
}

public static Member localMember(Long id, String email, String nickname, String password, String profileUrl) {
return new Member(id, email, nickname, "local", password, profileUrl, null, new HashSet<>());
public static Member localMember(Long id, MemberProfile profile) {
return new Member(id, profile);
}

public void addMemberRole(MemberRole memberRole) {
if (!this.roles.contains(memberRole)) {
roles.add(memberRole);
memberRole.setMember(this);
//** 연관 관계 엔티티 메서드 시작 **//
public void addMemberRole(MemberRole... memberRole) {
for (MemberRole role : memberRole) {
if (this.containsMemberRole(role)) {
continue;
}
this.roles.add(role);
if (role.getMember() != this) {
role.setMember(this);
}
}
}

public void addMemberRole(Set<MemberRole> memberRoleSet) {
for (MemberRole memberRole : memberRoleSet) {
addMemberRole(memberRole);
}
public void removeMemberRole(MemberRole memberRole) {
this.roles.remove(memberRole);
memberRole.setMember(null);
}

public void setMemberRoleSet(Set<MemberRole> memberRoleSet) {
this.roles = memberRoleSet;
public boolean containsMemberRole(MemberRole memberRole) {
for (MemberRole role : this.roles) {
if (role.equals(memberRole)) {
return true;
}
}
return false;
}

public void setNotificationPreference(NotificationPreference newPreference) {
this.notificationPreference = newPreference;
newPreference.setMember(this);
public void setNotificationPreference(NotificationPreference notificationPreference) {
if (this.notificationPreference != null) {
this.notificationPreference.setMember(null);
}
this.notificationPreference = notificationPreference;
if (notificationPreference != null && notificationPreference.getMember() != this) {
notificationPreference.setMember(this);
}
}

//** 연관 관계 엔티티 메서드 종료 **//
public boolean hasAuthorization(Long memberId) {
return id.equals(memberId);
}

public Member updateProfileUrl(String profileUrl) {
this.profileUrl = profileUrl;
return this;
public void changeProfileUrl(String profileUrl) {
profile.changeProfileUrl(profileUrl);
}

public void updatePassword(String newEncodedPassword) {
this.password = newEncodedPassword;
}

public void updateNickname(String nickname) {
this.nickname = nickname;
public void changeNickname(String nickname) {
this.profile.changeNickname(nickname);
}

public Collection<GrantedAuthority> getSimpleGrantedAuthorities() {
Expand All @@ -123,20 +122,43 @@ public Collection<GrantedAuthority> getSimpleGrantedAuthorities() {
.collect(Collectors.toSet());
}

public Map<String, Object> toMemberAttributeMap() {
public Map<String, Object> toAttributeMap() {
Map<String, Object> result = new HashMap<>();
result.put("id", id);
result.put("email", email);
result.put("nickname", nickname);
result.put("provider", provider);
result.put("profileUrl", profileUrl);
result.put("roleSet", roles.stream()
result.putAll(profile.toMap());
result.put("roles", roles.stream()
.map(MemberRole::getRoleName)
.collect(Collectors.toSet()));
.collect(Collectors.toUnmodifiableSet()));
return result;
}

public Optional<String> getPassword() {
return profile.getPassword();
}

public String getProvider() {
return profile.getProvider();
}

public String getNickname() {
return profile.getNickname();
}

public String getEmail() {
return profile.getEmail();
}

public Optional<String> getProfileUrl() {
return profile.getProfileUrl();
}

public Set<MemberRole> getRoles() {
return Collections.unmodifiableSet(roles);
}

@Override
public String toString() {
return String.format("Member(id=%d, nickname=%s, email=%s, roles=%s)", id, getNickname(), getEmail(),
getSimpleGrantedAuthorities());
}
}
Loading

0 comments on commit 234a6aa

Please sign in to comment.