Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 1 addition & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,6 @@
- app-network


volumes:
redis-data:

networks:
app-network:
name: app-network
name: hyetaekon-network
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
package com.hyetaekon.hyetaekon.UserInterest.controller;

import com.hyetaekon.hyetaekon.UserInterest.dto.UserInterestRequestDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.UserInterestResponseDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.CategorizedInterestsResponseDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.CategorizedInterestsWithSelectionDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.InterestSelectionRequestDto;
import com.hyetaekon.hyetaekon.UserInterest.entity.UserInterestEnum;
import com.hyetaekon.hyetaekon.UserInterest.service.UserInterestService;
import com.hyetaekon.hyetaekon.common.jwt.CustomUserDetails;
Expand All @@ -13,6 +14,7 @@

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@RestController
Expand All @@ -24,31 +26,32 @@ public class UserInterestController {

// ์„ ํƒํ•  ํ‚ค์›Œ๋“œ ๋ชฉ๋ก ์กฐํšŒ
@GetMapping
public ResponseEntity<UserInterestResponseDto> getAvailableInterests() {
// Enum์—์„œ displayName ๊ฐ’ ์ถ”์ถœ
List<String> Interests = Arrays.stream(UserInterestEnum.values())
.map(UserInterestEnum::getDisplayName)
.collect(Collectors.toList());
return ResponseEntity.ok(new UserInterestResponseDto(Interests));
public ResponseEntity<CategorizedInterestsResponseDto> getAvailableInterests() {
// Enum์—์„œ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„ displayName ๊ฐ’ ์ถ”์ถœ
Map<String, List<String>> categorizedInterests = Arrays.stream(UserInterestEnum.values())
.collect(Collectors.groupingBy(
UserInterestEnum::getCategory,
Collectors.mapping(UserInterestEnum::getDisplayName, Collectors.toList())
));
return ResponseEntity.ok(new CategorizedInterestsResponseDto(categorizedInterests));
}


// ๊ฐœ์ธ ํ‚ค์›Œ๋“œ ๋ชฉ๋ก ์กฐํšŒ
// ๋ชจ๋“  ๊ด€์‹ฌ์‚ฌ์™€ ์‚ฌ์šฉ์ž ์„ ํƒ ์—ฌ๋ถ€ ์กฐํšŒ
@GetMapping("/me")
public ResponseEntity<UserInterestResponseDto> getMyInterest(@AuthenticationPrincipal CustomUserDetails userDetails) {
public ResponseEntity<CategorizedInterestsWithSelectionDto> getMyInterestsWithSelection(
@AuthenticationPrincipal CustomUserDetails userDetails) {
Long userId = userDetails.getId();
return ResponseEntity.ok(userInterestService.getUserInterestsByUserId(userId));
return ResponseEntity.ok(userInterestService.getUserInterestsWithSelection(userId));
}

// ์„ ํƒํ•œ ํ‚ค์›Œ๋“œ ๋ชฉ๋ก ์ €์žฅ
// ์„ ํƒํ•œ ๊ด€์‹ฌ์‚ฌ ์ €์žฅ
@PostMapping("/me")
public ResponseEntity<Void> replaceInterests(
public ResponseEntity<Void> saveInterests(
@AuthenticationPrincipal CustomUserDetails userDetails,
@RequestBody UserInterestRequestDto UserInterestRequest
@RequestBody InterestSelectionRequestDto requestDto
) {
Long userId = userDetails.getId();
List<String> Interests = UserInterestRequest.getInterests();
userInterestService.replaceUserInterests(userId, Interests);
userInterestService.saveUserInterests(userId, requestDto.getAllInterests());
return ResponseEntity.status(HttpStatus.OK).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.hyetaekon.hyetaekon.UserInterest.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.Setter;

import java.util.List;
import java.util.Map;

@Getter
@AllArgsConstructor
public class CategorizedInterestsResponseDto {
private Map<String, List<String>> categorizedInterests;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
import lombok.Getter;

import java.util.List;

import java.util.Map;

@Getter
@AllArgsConstructor
public class UserInterestResponseDto {
private List<String> interests;
public class CategorizedInterestsWithSelectionDto {
private Map<String, List<InterestItemDto>> categorizedInterests;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.hyetaekon.hyetaekon.UserInterest.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

@Getter
@AllArgsConstructor
public class InterestItemDto {
private String name; // ๊ด€์‹ฌ์‚ฌ ์ด๋ฆ„
private boolean selected; // ์„ ํƒ ์—ฌ๋ถ€
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.hyetaekon.hyetaekon.UserInterest.dto;

import lombok.Getter;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Getter
public class InterestSelectionRequestDto {
private Map<String, List<String>> categorizedInterests;

// ๊ธฐ์กด ํ•„๋“œ ์œ ์ง€
private List<String> selectedInterests;

// categorizedInterests์—์„œ ๋ชจ๋“  ๊ด€์‹ฌ์‚ฌ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๋ฉ”์†Œ๋“œ
public List<String> getAllInterests() {
if (selectedInterests != null) {
return selectedInterests;
}

if (categorizedInterests == null) {
return new ArrayList<>();
}

List<String> allInterests = new ArrayList<>();
categorizedInterests.values().forEach(allInterests::addAll);
return allInterests;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,36 @@
@Getter
public enum UserInterestEnum {
// ServiceCategory ๊ด€๋ จ ๊ด€์‹ฌ์‚ฌ
CHILDCARE_EDUCATION("๋ณด์œกยท๊ต์œก"),
HOUSING_INDEPENDENCE("์ฃผ๊ฑฐยท์ž๋ฆฝ"),
ADMINISTRATION_SAFETY("ํ–‰์ •ยท์•ˆ์ „"),
AGRICULTURE_FISHERY("๋†๋ฆผ์ถ•์‚ฐ์–ด์—…"),
EMPLOYMENT_STARTUP("๊ณ ์šฉยท์ฐฝ์—…"),
HEALTH_MEDICAL("๋ณด๊ฑดยท์˜๋ฃŒ"),
CULTURE_ENVIRONMENT("๋ฌธํ™”ยทํ™˜๊ฒฝ"),
LIFE_STABILITY("์ƒํ™œ์•ˆ์ •"),
CHILDCARE_EDUCATION("๋ณด์œกยท๊ต์œก", "๊ด€์‹ฌ์ฃผ์ œ"),
HOUSING_INDEPENDENCE("์ฃผ๊ฑฐยท์ž๋ฆฝ", "๊ด€์‹ฌ์ฃผ์ œ"),
ADMINISTRATION_SAFETY("ํ–‰์ •ยท์•ˆ์ „", "๊ด€์‹ฌ์ฃผ์ œ"),
AGRICULTURE_FISHERY("๋†๋ฆผ์ถ•์‚ฐ์–ด์—…", "๊ด€์‹ฌ์ฃผ์ œ"),
EMPLOYMENT_STARTUP("๊ณ ์šฉยท์ฐฝ์—…", "๊ด€์‹ฌ์ฃผ์ œ"),
HEALTH_MEDICAL("๋ณด๊ฑดยท์˜๋ฃŒ", "๊ด€์‹ฌ์ฃผ์ œ"),
CULTURE_ENVIRONMENT("๋ฌธํ™”ยทํ™˜๊ฒฝ", "๊ด€์‹ฌ์ฃผ์ œ"),
LIFE_STABILITY("์ƒํ™œ์•ˆ์ •", "๊ด€์‹ฌ์ฃผ์ œ"),

// SpecialGroup ๊ด€๋ จ ๊ด€์‹ฌ์‚ฌ
IS_MULTI_CULTURAL("๋‹ค๋ฌธํ™”๊ฐ€์กฑ"),
IS_NORTH_KOREAN_DEFECTOR("๋ถํ•œ์ดํƒˆ์ฃผ๋ฏผ"),
IS_SINGLE_PARENT_FAMILY("ํ•œ๋ถ€๋ชจ๊ฐ€์ •/์กฐ์†๊ฐ€์ •"),
IS_SINGLE_MEMBER_HOUSEHOLD("1์ธ๊ฐ€๊ตฌ"),
IS_DISABLED("์žฅ์• ์ธ"),
IS_NATIONAL_MERIT_RECIPIENT("๊ตญ๊ฐ€๋ณดํ›ˆ๋Œ€์ƒ์ž"),
IS_CHRONIC_ILLNESS("์งˆ๋ณ‘/์งˆํ™˜์ž"),
IS_MULTI_CULTURAL("๋‹ค๋ฌธํ™”๊ฐ€์กฑ", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_NORTH_KOREAN_DEFECTOR("๋ถํ•œ์ดํƒˆ์ฃผ๋ฏผ", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_SINGLE_PARENT_FAMILY("ํ•œ๋ถ€๋ชจ๊ฐ€์ •/์กฐ์†๊ฐ€์ •", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_SINGLE_MEMBER_HOUSEHOLD("1์ธ๊ฐ€๊ตฌ", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_DISABLED("์žฅ์• ์ธ", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_NATIONAL_MERIT_RECIPIENT("๊ตญ๊ฐ€๋ณดํ›ˆ๋Œ€์ƒ์ž", "๊ฐ€๊ตฌํ˜•ํƒœ"),
IS_CHRONIC_ILLNESS("์งˆ๋ณ‘/์งˆํ™˜์ž", "๊ฐ€๊ตฌํ˜•ํƒœ"),

// FamilyType ๊ด€๋ จ ๊ด€์‹ฌ์‚ฌ
// IS_NOT_APPLICABLE("ํ•ด๋‹น์‚ฌํ•ญ ์—†์Œ"),
IS_MULTI_CHILDREN_FAMILY("๋‹ค์ž๋…€๊ฐ€๊ตฌ"),
IS_NON_HOUSING_HOUSEHOLD("๋ฌด์ฃผํƒ์„ธ๋Œ€"),
IS_NEW_RESIDENCE("์‹ ๊ทœ์ „์ž…"),
IS_EXTENDED_FAMILY("ํ™•๋Œ€๊ฐ€์กฑ");
// IS_NOT_APPLICABLE("ํ•ด๋‹น์‚ฌํ•ญ ์—†์Œ", "๊ฐ€๊ตฌ์ƒํ™ฉ"),
IS_MULTI_CHILDREN_FAMILY("๋‹ค์ž๋…€๊ฐ€๊ตฌ", "๊ฐ€๊ตฌ์ƒํ™ฉ"),
IS_NON_HOUSING_HOUSEHOLD("๋ฌด์ฃผํƒ์„ธ๋Œ€", "๊ฐ€๊ตฌ์ƒํ™ฉ"),
IS_NEW_RESIDENCE("์‹ ๊ทœ์ „์ž…", "๊ฐ€๊ตฌ์ƒํ™ฉ"),
IS_EXTENDED_FAMILY("ํ™•๋Œ€๊ฐ€์กฑ", "๊ฐ€๊ตฌ์ƒํ™ฉ");

private final String displayName;
private final String category;

UserInterestEnum(String displayName) {
UserInterestEnum(String displayName, String category) {
this.displayName = displayName;
this.category = category;
}

}
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package com.hyetaekon.hyetaekon.UserInterest.service;

import com.hyetaekon.hyetaekon.UserInterest.dto.UserInterestResponseDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.CategorizedInterestsWithSelectionDto;
import com.hyetaekon.hyetaekon.UserInterest.dto.InterestItemDto;
import com.hyetaekon.hyetaekon.UserInterest.entity.UserInterest;
import com.hyetaekon.hyetaekon.UserInterest.entity.UserInterestEnum;
import com.hyetaekon.hyetaekon.UserInterest.repository.UserInterestRepository;
import com.hyetaekon.hyetaekon.common.exception.ErrorCode;
import com.hyetaekon.hyetaekon.common.exception.GlobalException;
Expand All @@ -12,7 +14,8 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
Expand All @@ -21,26 +24,58 @@ public class UserInterestService {
private final UserRepository userRepository;
private final UserInterestRepository userInterestRepository;

// ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ ์กฐํšŒ
// ๋ชจ๋“  ๊ด€์‹ฌ์‚ฌ ๋ชฉ๋ก๊ณผ ์‚ฌ์šฉ์ž ์„ ํƒ ์—ฌ๋ถ€ ํ•จ๊ป˜ ์กฐํšŒ
@Transactional(readOnly = true)
public UserInterestResponseDto getUserInterestsByUserId(Long userId) {
public CategorizedInterestsWithSelectionDto getUserInterestsWithSelection(Long userId) {
User user = userRepository.findByIdAndDeletedAtIsNull(userId)
.orElseThrow(() -> new GlobalException(ErrorCode.USER_NOT_FOUND_BY_ID));

List<String> userInterests = user.getInterests().stream()
// ์‚ฌ์šฉ์ž๊ฐ€ ์„ ํƒํ•œ ๊ด€์‹ฌ์‚ฌ ๋ชฉ๋ก
List<String> selectedInterests = user.getInterests().stream()
.map(UserInterest::getInterest)
.toList();

log.debug("ํšŒ์› ๊ด€์‹ฌ์‚ฌ ์กฐํšŒ - ์œ ์ € ID: {}, ๊ด€์‹ฌ์‚ฌ: {}", userId, userInterests);
return new UserInterestResponseDto(userInterests);
// ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„๋กœ ๋ชจ๋“  ๊ด€์‹ฌ์‚ฌ๋ฅผ ํฌํ•จํ•˜๋˜, ์„ ํƒ ์—ฌ๋ถ€ ํ‘œ์‹œ
Map<String, List<InterestItemDto>> result = new HashMap<>();

Arrays.stream(UserInterestEnum.values())
.forEach(interestEnum -> {
String category = interestEnum.getCategory();
String displayName = interestEnum.getDisplayName();
boolean isSelected = selectedInterests.contains(displayName);

if (!result.containsKey(category)) {
result.put(category, new ArrayList<>());
}

result.get(category).add(new InterestItemDto(displayName, isSelected));
});

log.debug("ํšŒ์› ๊ด€์‹ฌ์‚ฌ ์กฐํšŒ (์„ ํƒ ์—ฌ๋ถ€ ํฌํ•จ) - ์œ ์ € ID: {}", userId);
return new CategorizedInterestsWithSelectionDto(result);
}

// ์„ ํƒํ•œ ๊ด€์‹ฌ์‚ฌ ์ €์žฅ
@Transactional
public void replaceUserInterests(Long userId, List<String> Interests) {
// Validate Interest size (optional, assuming max 5)
if (Interests.size() > 5) {
throw new GlobalException(
ErrorCode.INTEREST_LIMIT_EXCEEDED); // Custom error for exceeding limit
public void saveUserInterests(Long userId, List<String> selectedInterests) {
if (selectedInterests == null) {
selectedInterests = new ArrayList<>(); // ๋นˆ ๋ฆฌ์ŠคํŠธ๋กœ ์ดˆ๊ธฐํ™”
}

// ์ตœ๋Œ€ ์„ ํƒ ๊ฐœ์ˆ˜ ๊ฒ€์ฆ
if (selectedInterests.size() > 5) {
throw new GlobalException(ErrorCode.INTEREST_LIMIT_EXCEEDED);
}

// ์œ ํšจํ•œ ๊ด€์‹ฌ์‚ฌ์ธ์ง€ ๊ฒ€์ฆ
Set<String> validInterests = Arrays.stream(UserInterestEnum.values())
.map(UserInterestEnum::getDisplayName)
.collect(Collectors.toSet());

for (String interest : selectedInterests) {
if (!validInterests.contains(interest)) {
throw new GlobalException(ErrorCode.INVALID_INTEREST);
}
}

User user = userRepository.findByIdAndDeletedAtIsNull(userId)
Expand All @@ -50,14 +85,30 @@ public void replaceUserInterests(Long userId, List<String> Interests) {
user.getInterests().clear();

// ์ƒˆ ๊ด€์‹ฌ์‚ฌ ์ถ”๊ฐ€
for (String Interest : Interests) {
for (String interest : selectedInterests) {
UserInterest newInterest = UserInterest.builder()
.user(user)
.interest(Interest)
.interest(interest)
.build();
userInterestRepository.save(newInterest);
}

log.debug("ํšŒ์› ๊ด€์‹ฌ์‚ฌ ๊ฐฑ์‹  - ์œ ์ € ID: {}, ์ƒˆ ๊ด€์‹ฌ์‚ฌ ๋ชฉ๋ก: {}", userId, Interests);
log.debug("ํšŒ์› ๊ด€์‹ฌ์‚ฌ ๊ฐฑ์‹  - ์œ ์ € ID: {}, ์„ ํƒ ๊ด€์‹ฌ์‚ฌ: {}", userId, selectedInterests);
}

/* // ๋‚˜์˜ ๊ด€์‹ฌ์‚ฌ ์กฐํšŒ
@Transactional(readOnly = true)
public UserInterestResponseDto getUserInterestsByUserId(Long userId) {
User user = userRepository.findByIdAndDeletedAtIsNull(userId)
.orElseThrow(() -> new GlobalException(ErrorCode.USER_NOT_FOUND_BY_ID));

List<String> userInterests = user.getInterests().stream()
.map(UserInterest::getInterest)
.toList();

log.debug("ํšŒ์› ๊ด€์‹ฌ์‚ฌ ์กฐํšŒ - ์œ ์ € ID: {}, ๊ด€์‹ฌ์‚ฌ: {}", userId, userInterests);
return new UserInterestResponseDto(userInterests);
}

*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public class SecurityPath {
"/",
"/api/services",
"/api/services/category/*",
"/api/services/detail/*"
"/api/services/detail/*",
"/api/public-data/serviceList/test"
};


Expand All @@ -32,7 +33,7 @@ public class SecurityPath {
"/api/admin/users/**",
"/api/public-data/serviceDetailList",
"/api/public-data/supportConditionsList",
"/api/public-data/serviceList/**"
"/api/public-data/serviceList"
};
}

Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public enum ErrorCode {
FORBIDDEN_ACCESS(HttpStatus.FORBIDDEN, "AUTH-011", "์ž˜๋ชป๋œ ์ ‘๊ทผ์ž…๋‹ˆ๋‹ค."),
NOT_SUSPENDED_USER(HttpStatus.BAD_REQUEST, "ACCOUNT-008", "์ •์ง€ ์ƒํƒœ๊ฐ€ ์•„๋‹Œ ํšŒ์›์ž…๋‹ˆ๋‹ค."),
INVALID_SUSPEND_TIME(HttpStatus.BAD_REQUEST, "ACCOUNT-009", "์ •์ง€ ๊ธฐ๊ฐ„์ด ์œ ํšจํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."),
PASSWORD_CONFIRM_MISMATCH(HttpStatus.BAD_REQUEST, "ACCOUNT-010", "์ƒˆ ๋น„๋ฐ€๋ฒˆํ˜ธ์™€ ํ™•์ธ ๋น„๋ฐ€๋ฒˆํ˜ธ๊ฐ€ ์ผ์น˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค."),

// ๋ถ๋งˆํฌ
BOOKMARK_USER_NOT_FOUND(HttpStatus.NOT_FOUND, "BOOKMARK-001", "๋ถ๋งˆํฌํ•œ ์œ ์ €๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค."),
Expand All @@ -43,6 +44,7 @@ public enum ErrorCode {

// ๊ด€์‹ฌ์‚ฌ ์„ ํƒ ์ œํ•œ
INTEREST_LIMIT_EXCEEDED(HttpStatus.BAD_REQUEST, "INTEREST-001", "๊ด€์‹ฌ์‚ฌ๋Š” ์ตœ๋Œ€ 6๊ฐœ๊นŒ์ง€๋งŒ ๋“ฑ๋ก ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค."),
INVALID_INTEREST(HttpStatus.BAD_REQUEST, "INTEREST-002", "์œ ํšจํ•˜์ง€ ์•Š์€ ๊ด€์‹ฌ์‚ฌ์ž…๋‹ˆ๋‹ค."),

// ๊ณต๊ณต์„œ๋น„์Šค
// ์œ ํšจ JACODE ํ™•์ธ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public ResponseEntity<String> createAndStoreSupportConditionsList() {
/**
* ํŽ˜์ด์ง€ ๋‹จ์œ„ ๊ณต๊ณต์„œ๋น„์Šค ๋ชฉ๋ก ์กฐํšŒ (ํ…Œ์ŠคํŠธ์šฉ)
*/
@GetMapping("/serviceList")
@GetMapping("/serviceList/test")
public ResponseEntity<List<PublicServiceDataDto.Data>> getServiceListByPage(
@RequestParam(defaultValue = "1") int page,
@RequestParam(defaultValue = "100") int perPage) {
Expand Down
Loading