Skip to content

Commit

Permalink
Merge branch 'feat/user' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
wwingyou committed Jan 27, 2025
2 parents 57ade0d + 5a6aee1 commit ce0c660
Show file tree
Hide file tree
Showing 12 changed files with 308 additions and 137 deletions.
31 changes: 31 additions & 0 deletions src/main/java/com/goolbitg/api/entity/SpendingType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.goolbitg.api.entity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.Table;

import lombok.Getter;

/**
* SpendingType
*/
@Entity
@Table(name = "spending_types")
@Getter
public class SpendingType {

@Id
@Column(name = "id")
private String id;

@Column(name = "title")
private String title;

@Column(name = "image_url")
private String imageUrl;

@Column(name = "cutline")
private Integer cutline;

}
2 changes: 1 addition & 1 deletion src/main/java/com/goolbitg/api/entity/UserStats.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@ public class UserStats {
private Integer postCount;

@Column(name = "achivement_guage")
private Float achivementGuage;
private Integer achivementGuage;

}
22 changes: 19 additions & 3 deletions src/main/java/com/goolbitg/api/entity/UserSurvey.java
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,30 @@ public class UserSurvey {
@Column(name = "avg_spending_per_month")
private Integer avgSpendingPerMonth;

@Column(name = "spending_habit_score")
private Integer spendingHabitScore;

@Column(name = "prime_use_day")
@Enumerated(EnumType.STRING)
private Day primUseDay;

@Column(name = "prime_use_time")
private LocalTime primeUseTime;

public Integer getChecklistScore() {
if (check1 == null || check2 == null || check3 == null ||
check4 == null || check5 == null || check6 == null)
return null;
int count = 0;
if (check1) count++;
if (check2) count++;
if (check3) count++;
if (check4) count++;
if (check5) count++;
if (check6) count++;
return (int)(count / 2);
}

public Integer getSpendingHabitScore() {
if (avgIncomePerMonth == null || avgSpendingPerMonth == null)
return null;
return (int)(100.0 - ((float)avgSpendingPerMonth / avgIncomePerMonth) * 100.0);
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/goolbitg/api/exception/UserException.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,11 @@ public static CommonException registrationNotComplete(String id) {
"회원정보 입력이 완료되지 않았습니다. (" + id + ")",
HttpStatus.UNPROCESSABLE_ENTITY);
}
public static CommonException previousStepNotComplete(int status) {
return new CommonException(
3004,
"이전 단계의 정보 입력이 완료되지 않았습니다. (" + status + ")",
HttpStatus.UNPROCESSABLE_ENTITY);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.goolbitg.api.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.goolbitg.api.entity.SpendingType;

/**
* SpendingTypeRepository
*/
public interface SpendingTypeRepository extends JpaRepository<SpendingType, String> {

}
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
package com.goolbitg.api.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.repository.CrudRepository;

import com.goolbitg.api.entity.UserSurvey;

/**
* UserSurveyRepository
*/
public interface UserSurveyRepository extends CrudRepository<UserSurvey, String> {
public interface UserSurveyRepository extends JpaRepository<UserSurvey, String> {

}
169 changes: 107 additions & 62 deletions src/main/java/com/goolbitg/api/service/UserServiceImpl.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.goolbitg.api.service;

import java.math.BigInteger;
import java.net.URI;
import java.security.SecureRandom;
import java.time.LocalDate;
import java.util.Optional;
Expand All @@ -13,6 +14,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.goolbitg.api.entity.SpendingType;
import com.goolbitg.api.entity.User;
import com.goolbitg.api.entity.UserStats;
import com.goolbitg.api.entity.UserSurvey;
Expand All @@ -23,6 +25,7 @@
import com.goolbitg.api.model.LoginType;
import com.goolbitg.api.model.NicknameCheckRequestDto;
import com.goolbitg.api.model.NicknameCheckResponseDto;
import com.goolbitg.api.model.SpendingTypeDto;
import com.goolbitg.api.model.TokenRefreshRequestDto;
import com.goolbitg.api.model.UserAgreementDto;
import com.goolbitg.api.model.UserChecklistDto;
Expand All @@ -31,6 +34,7 @@
import com.goolbitg.api.model.UserInfoDto;
import com.goolbitg.api.model.UserPatternDto;
import com.goolbitg.api.model.UserRegisterStatusDto;
import com.goolbitg.api.repository.SpendingTypeRepository;
import com.goolbitg.api.repository.UserRepository;
import com.goolbitg.api.repository.UserStatsRepository;
import com.goolbitg.api.repository.UserSurveyRepository;
Expand Down Expand Up @@ -59,6 +63,8 @@ public class UserServiceImpl implements UserService {
@Autowired
private final UserTokenRepository tokenRepository;
@Autowired
private final SpendingTypeRepository spendingTypeRepository;
@Autowired
private final JwtManager jwtManager;

private int idSeq = 2;
Expand All @@ -73,9 +79,12 @@ public UserDto getUser(String userId) throws Exception {
UserStats stats = userStatsRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));

log.info("User: " + user);
return getUserDto(user, survey, stats);
}

private UserDto getUserDto(User user, UserSurvey survey, UserStats stats) {
UserDto dto = new UserDto();
dto.setId(userId);
dto.setId(user.getId());
dto.setNickname(user.getNickname());
dto.setBirthday(user.getBirthday());
dto.setGender(user.getGender());
Expand All @@ -87,6 +96,19 @@ public UserDto getUser(String userId) throws Exception {
dto.setCheck6(survey.getCheck6());
dto.setAvgIncomePerMonth(survey.getAvgIncomePerMonth());
dto.setAvgSpendingPerMonth(survey.getAvgSpendingPerMonth());
dto.setPostCount(stats.getPostCount());
dto.setChallengeCount(stats.getChallengeCount());
dto.setAchivementGuage(stats.getAchivementGuage());

if (user.getSpendingTypeId() != null) {
SpendingType spendingType =
spendingTypeRepository.findById(user.getSpendingTypeId()).get();
SpendingTypeDto spendingTypeDto = new SpendingTypeDto();
spendingTypeDto.setId(spendingType.getId());
spendingTypeDto.setTitle(spendingType.getTitle());
spendingTypeDto.setImageUrl(URI.create(spendingType.getImageUrl()));
dto.setSpendingType(spendingTypeDto);
}

if (survey.getPrimUseDay() != null)
dto.setPrimeUseDay(survey.getPrimUseDay().getValue());
Expand Down Expand Up @@ -163,45 +185,6 @@ public AuthResponseDto getAccessToken(TokenRefreshRequestDto request) {
return dto;
}

private String createRefreshToken(String userId) {
String token = RandomHolder.randomKey(128);
tokenRepository.save(userId, token);
return token;
}

private static class RandomHolder {
static final Random random = new SecureRandom();
public static String randomKey(int length) {
return String.format("%"+length+"s", new BigInteger(length*5, random)
.toString(32)).replace('\u0020', '0');
}
}

private Jwt extractToken(AuthRequestDto request) {
String jwkUri;
if (request.getType() == LoginType.KAKAO) {
jwkUri = "https://kauth.kakao.com/.well-known/jwks.json";
} else {
jwkUri = "https://appleid.apple.com/auth/keys";
}
JwtDecoder decoder = NimbusJwtDecoder
.withJwkSetUri(jwkUri)
.build();
Jwt jwt = decoder.decode(request.getIdToken());
return jwt;
}

private Optional<User> findUser(Jwt jwt, AuthRequestDto request) {
String id = jwt.getSubject();
Optional<User> result;
if (request.getType() == LoginType.KAKAO) {
result = userRepository.findByKakaoId(id);
} else {
result = userRepository.findByAppleId(id);
}
return result;
}

@Override
public void logout(String userId) {
tokenRepository.deleteByUserId(userId);
Expand All @@ -217,10 +200,10 @@ public NicknameCheckResponseDto isNicknameExist(NicknameCheckRequestDto nickname
@Override
@Transactional
public void updateUserInfo(String userId, UserInfoDto request) {
Optional<User> result = userRepository.findById(userId);
if (result.isEmpty()) {
throw UserException.userNotExist(userId);
}
User user = userRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));
if (user.getAgreement1() == null)
throw UserException.previousStepNotComplete(0);

if (isNicknameExistInner(request.getNickname())) {
// TODO: Integrated validation error message required.
Expand All @@ -229,7 +212,6 @@ public void updateUserInfo(String userId, UserInfoDto request) {
);
}

User user = result.get();
user.setNickname(request.getNickname());
user.setBirthday(request.getBirthday());
user.setGender(request.getGender());
Expand All @@ -239,12 +221,14 @@ public void updateUserInfo(String userId, UserInfoDto request) {
@Override
@Transactional
public void updateChecklistInfo(String userId, UserChecklistDto request) {
Optional<UserSurvey> result = userSurveyRepository.findById(userId);
if (result.isEmpty()) {
throw UserException.userNotExist(userId);
}
User user = userRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));
if (user.getNickname() == null)
throw UserException.previousStepNotComplete(1);

UserSurvey survey = userSurveyRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));

UserSurvey survey = result.get();
survey.setCheck1(request.getCheck1());
survey.setCheck2(request.getCheck2());
survey.setCheck3(request.getCheck3());
Expand All @@ -257,16 +241,19 @@ public void updateChecklistInfo(String userId, UserChecklistDto request) {
@Override
@Transactional
public void updateHabitinfo(String userId, UserHabitDto request) {
Optional<UserSurvey> result = userSurveyRepository.findById(userId);
if (result.isEmpty()) {
throw UserException.userNotExist(userId);
}
User user = userRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));
if (user.getNickname() == null)
throw UserException.previousStepNotComplete(1);

UserSurvey survey = userSurveyRepository.findById(userId)
.orElseThrow(() -> UserException.userNotExist(userId));

UserSurvey survey = result.get();
survey.setAvgIncomePerMonth(request.getAvgIncomePerMonth());
survey.setAvgSpendingPerMonth(request.getAvgSpendingPerMonth());
// TODO: spending score calculation logic
user.setSpendingTypeId(determineSpendingType(survey));
userSurveyRepository.save(survey);
userRepository.save(user);
}

@Override
Expand All @@ -284,11 +271,6 @@ public void updatePatternInfo(String userId, UserPatternDto request) {
userSurveyRepository.save(survey);
}

private boolean isNicknameExistInner(String nickname) {
Optional<User> result = userRepository.findByNickname(nickname);
return result.isPresent();
}

@Override
@Transactional
public void unregister(String userId) {
Expand Down Expand Up @@ -351,4 +333,67 @@ private int getRegisterStatusInner(User user, UserSurvey survey) {
if (survey.getPrimUseDay() == null) return 4;
return 5;
}

private String createRefreshToken(String userId) {
String token = RandomHolder.randomKey(128);
tokenRepository.save(userId, token);
return token;
}

private static class RandomHolder {
static final Random random = new SecureRandom();
public static String randomKey(int length) {
return String.format("%"+length+"s", new BigInteger(length*5, random)
.toString(32)).replace('\u0020', '0');
}
}

private Jwt extractToken(AuthRequestDto request) {
String jwkUri;
if (request.getType() == LoginType.KAKAO) {
jwkUri = "https://kauth.kakao.com/.well-known/jwks.json";
} else {
jwkUri = "https://appleid.apple.com/auth/keys";
}
JwtDecoder decoder = NimbusJwtDecoder
.withJwkSetUri(jwkUri)
.build();
Jwt jwt = decoder.decode(request.getIdToken());
return jwt;
}

private Optional<User> findUser(Jwt jwt, AuthRequestDto request) {
String id = jwt.getSubject();
Optional<User> result;
if (request.getType() == LoginType.KAKAO) {
result = userRepository.findByKakaoId(id);
} else {
result = userRepository.findByAppleId(id);
}
return result;
}

private boolean isNicknameExistInner(String nickname) {
Optional<User> result = userRepository.findByNickname(nickname);
return result.isPresent();
}

private String determineSpendingType(UserSurvey survey) {
Integer checklistScore = survey.getChecklistScore();
Integer spendingHabitScore = survey.getSpendingHabitScore();
if (checklistScore == null || spendingHabitScore == null)
throw UserException.registrationNotComplete(survey.getUserId());

if (checklistScore == 3 || spendingHabitScore < 50)
return "st01";
if (checklistScore == 2 || spendingHabitScore < 70)
return "st02";
if (checklistScore == 1 || spendingHabitScore < 80)
return "st03";
if (checklistScore == 0 || spendingHabitScore < 90)
return "st04";

return "st05";
}

}
Loading

0 comments on commit ce0c660

Please sign in to comment.