From 10228f80bd22f7897e17838a0e7ba79b559e5192 Mon Sep 17 00:00:00 2001 From: melonhong Date: Sat, 29 Nov 2025 17:35:54 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20UserInfo=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EB=B0=8F=20=EB=A0=88=ED=8F=AC=EC=A7=80=ED=86=A0?= =?UTF-8?q?=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/fitlink/domain/UsersInfo.java | 36 +++++++++++++++++++ .../java/com/fitlink/domain/enums/Sex.java | 8 +++++ .../repository/UsersInfoRepository.java | 7 ++++ 3 files changed, 51 insertions(+) create mode 100644 src/main/java/com/fitlink/domain/UsersInfo.java create mode 100644 src/main/java/com/fitlink/domain/enums/Sex.java create mode 100644 src/main/java/com/fitlink/repository/UsersInfoRepository.java diff --git a/src/main/java/com/fitlink/domain/UsersInfo.java b/src/main/java/com/fitlink/domain/UsersInfo.java new file mode 100644 index 0000000..909b1ca --- /dev/null +++ b/src/main/java/com/fitlink/domain/UsersInfo.java @@ -0,0 +1,36 @@ +package com.fitlink.domain; + +import com.fitlink.domain.enums.Sex; +import jakarta.persistence.*; +import lombok.*; +import lombok.experimental.SuperBuilder; + +@Entity +@Table(name = "users_info") +@Getter +@Setter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@SuperBuilder +public class UsersInfo { + + @Id + @Column(name = "users_id") + private Long usersId; + + // @MapsId: Users의 PK를 가져와서 자신의 PK이자 FK로 사용 + @OneToOne(fetch = FetchType.LAZY) + @MapsId + @JoinColumn(name = "users_id") + private Users users; + + private Float height; + + private Float weight; + + @Column(length = 8) // YYYYMMDD + private String birthDate; + + @Enumerated(EnumType.STRING) + @Column(columnDefinition = "enum('M', 'F')") + private Sex sex; +} \ No newline at end of file diff --git a/src/main/java/com/fitlink/domain/enums/Sex.java b/src/main/java/com/fitlink/domain/enums/Sex.java new file mode 100644 index 0000000..fe76751 --- /dev/null +++ b/src/main/java/com/fitlink/domain/enums/Sex.java @@ -0,0 +1,8 @@ +package com.fitlink.domain.enums; + +/** + * 성별 enum. + */ +public enum Sex { + M, F +} diff --git a/src/main/java/com/fitlink/repository/UsersInfoRepository.java b/src/main/java/com/fitlink/repository/UsersInfoRepository.java new file mode 100644 index 0000000..33ba828 --- /dev/null +++ b/src/main/java/com/fitlink/repository/UsersInfoRepository.java @@ -0,0 +1,7 @@ +package com.fitlink.repository; + +import com.fitlink.domain.UsersInfo; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface UsersInfoRepository extends JpaRepository { +} From a924ad830972a6650c952cae50052d00636d926c Mon Sep 17 00:00:00 2001 From: melonhong Date: Sat, 29 Nov 2025 17:36:06 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20UserInfoMapper=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fitlink/web/mapper/UserInfoMapper.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/main/java/com/fitlink/web/mapper/UserInfoMapper.java diff --git a/src/main/java/com/fitlink/web/mapper/UserInfoMapper.java b/src/main/java/com/fitlink/web/mapper/UserInfoMapper.java new file mode 100644 index 0000000..6eb3ed4 --- /dev/null +++ b/src/main/java/com/fitlink/web/mapper/UserInfoMapper.java @@ -0,0 +1,21 @@ +package com.fitlink.web.mapper; + +import com.fitlink.domain.UsersInfo; +import com.fitlink.web.dto.FitnessResponseDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.MappingTarget; + +@Mapper(componentModel = "spring") +public interface UserInfoMapper { + + FitnessResponseDTO.UserInfo toDTO(UsersInfo entity); + + @Mapping(target = "users", ignore = true) + @Mapping(target = "usersId", ignore = true) + UsersInfo toEntity(FitnessResponseDTO.UserInfo dto); + + @Mapping(target = "users", ignore = true) + @Mapping(target = "usersId", ignore = true) + void updateEntityFromDto(FitnessResponseDTO.UserInfo dto, @MappingTarget UsersInfo entity); +} \ No newline at end of file From 6539ffe0c6e649d83157661904cda7a53af6b935 Mon Sep 17 00:00:00 2001 From: melonhong Date: Sat, 29 Nov 2025 17:39:08 +0900 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20DTO=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FitnessResponseDTO: UserInfo 내부 클래스 추가 - FitnessController: UserInfo 관련 레포지토리, 매퍼를 추가함. users_info 테이블에 관련 데이터를 추가하는 메서드와 응답할 때 DTO에 UserInfo를 추가하는 로직도 추가함 --- .../web/controller/FitnessController.java | 54 ++++++++++++++++++- .../fitlink/web/dto/FitnessResponseDTO.java | 25 +++++++++ 2 files changed, 77 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fitlink/web/controller/FitnessController.java b/src/main/java/com/fitlink/web/controller/FitnessController.java index 8ad7d33..6df4441 100644 --- a/src/main/java/com/fitlink/web/controller/FitnessController.java +++ b/src/main/java/com/fitlink/web/controller/FitnessController.java @@ -5,12 +5,16 @@ import com.fitlink.config.security.jwt.JwtTokenProvider; import com.fitlink.domain.FitnessResult; import com.fitlink.domain.Users; +import com.fitlink.domain.UsersInfo; +import com.fitlink.domain.enums.Sex; import com.fitlink.repository.FitnessResultRepository; +import com.fitlink.repository.UsersInfoRepository; import com.fitlink.service.fitness.FitnessScoreService; import com.fitlink.web.dto.FitnessGeneralRequestDTO; import com.fitlink.web.dto.FitnessKookminRequestDTO; import com.fitlink.web.dto.FitnessResponseDTO; import com.fitlink.web.mapper.FitnessResultMapper; +import com.fitlink.web.mapper.UserInfoMapper; import jakarta.servlet.http.HttpServletRequest; import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.*; @@ -24,19 +28,48 @@ public class FitnessController { private final JwtTokenProvider jwtTokenProvider; private final FitnessResultMapper fitnessResultMapper; + private final UserInfoMapper userInfoMapper; private final FitnessScoreService fitnessScoreService; private final FitnessResultRepository fitnessResultRepository; + private final UsersInfoRepository usersInfoRepository; public FitnessController( JwtTokenProvider jwtTokenProvider, - FitnessResultMapper fitnessResultMapper, + FitnessResultMapper fitnessResultMapper, UserInfoMapper userInfoMapper, FitnessScoreService fitnessScoreService, - FitnessResultRepository fitnessResultRepository + FitnessResultRepository fitnessResultRepository, UsersInfoRepository usersInfoRepository ) { this.jwtTokenProvider = jwtTokenProvider; this.fitnessResultMapper = fitnessResultMapper; + this.userInfoMapper = userInfoMapper; this.fitnessScoreService = fitnessScoreService; this.fitnessResultRepository = fitnessResultRepository; + this.usersInfoRepository = usersInfoRepository; + } + + /** + * users_info에 사용자의 성별, 키, 몸무게를 저장함. + * + * @param user 해당 사용자 엔티티 + * @param sexStr "M" 또는 "F" + * @param height 키 + * @param weight 몸무게 + * @return + */ + private FitnessResponseDTO.UserInfo saveOrUpdateUsersInfo(Users user, String sexStr, String birthDate, Float height, Float weight) { + UsersInfo userInfo = usersInfoRepository.findById(user.getId()) + .orElse(UsersInfo.builder() + .users(user) + .build()); + + // 값 업데이트 + userInfo.setSex(Sex.valueOf(sexStr)); // Enum 변환 + userInfo.setBirthDate(birthDate); + userInfo.setHeight(height); + userInfo.setWeight(weight); + + userInfo = usersInfoRepository.save(userInfo); + return userInfoMapper.toDTO(userInfo); } /** @@ -72,6 +105,10 @@ public ApiResponse postFitnessKf100( FitnessResult entity = fitnessResultMapper.toEntity(response, user); fitnessResultRepository.save(entity); + // users_info 테이블에 성별, 생년월일, 키, 몸무게 저장 후 응답 DTO에 추가 + FitnessResponseDTO.UserInfo userInfo = saveOrUpdateUsersInfo(user, request.getSex(), request.getBirthDate(), request.getHeight(), request.getWeight()); + response.setUserInfo(userInfo); + return ApiResponse.onSuccess(response); } @@ -93,6 +130,9 @@ public ApiResponse postFitnessGeneral( FitnessResult entity = fitnessResultMapper.toEntity(response, user); fitnessResultRepository.save(entity); + FitnessResponseDTO.UserInfo userInfo = saveOrUpdateUsersInfo(user, request.getSex(), request.getBirthDate(), request.getHeight(), request.getWeight()); + response.setUserInfo(userInfo); + return ApiResponse.onSuccess(response); } @@ -134,6 +174,9 @@ public ApiResponse patchFitnessKf100( // 업데이트 된 전체 결과 DTO response = fitnessResultMapper.toResponseDTO(existing); + FitnessResponseDTO.UserInfo userInfo = saveOrUpdateUsersInfo(user, request.getSex(), request.getBirthDate(), request.getHeight(), request.getWeight()); + response.setUserInfo(userInfo); + // 결과 DTO에 평균값 추가 response.setAverage(average); @@ -172,6 +215,9 @@ public ApiResponse patchFitnessGeneral( response = fitnessResultMapper.toResponseDTO(existing); + FitnessResponseDTO.UserInfo userInfo = saveOrUpdateUsersInfo(user, request.getSex(), request.getBirthDate(), request.getHeight(), request.getWeight()); + response.setUserInfo(userInfo); + response.setAverage(average); return ApiResponse.onSuccess(response); @@ -200,6 +246,10 @@ public ApiResponse getFitnessResult(HttpServletRequest httpS response = fitnessResultMapper.toResponseDTO(entity); + // 사용자 정보 가져오고 응답 DTO에 추가 + UsersInfo userInfo = usersInfoRepository.findById(user.getId()).orElse(null); + response.setUserInfo(userInfoMapper.toDTO(userInfo)); + return ApiResponse.onSuccess(response); } diff --git a/src/main/java/com/fitlink/web/dto/FitnessResponseDTO.java b/src/main/java/com/fitlink/web/dto/FitnessResponseDTO.java index f48416e..7f05e6a 100644 --- a/src/main/java/com/fitlink/web/dto/FitnessResponseDTO.java +++ b/src/main/java/com/fitlink/web/dto/FitnessResponseDTO.java @@ -30,6 +30,9 @@ public class FitnessResponseDTO { @Schema(description = "운동 종목별 대한민국 평균(기준) 데이터 객체") private FitnessAverage average; + @Schema(description = "사용자 신체 정보") + private UserInfo userInfo; + /** * 평균값 데이터를 담는 내부 클래스 */ @@ -58,4 +61,26 @@ public static class FitnessAverage { @Schema(description = "순발력(Quickness) 평균 - 제자리 멀리뛰기 측정값 기준") private Float standingLongJump; } + + /** + * 사용자의 정보를 담은 클래스 + */ + @NoArgsConstructor + @AllArgsConstructor + @Getter + @Setter + @Builder + public static class UserInfo { + @Schema(description = "성별(Sex) - 남성: 'M', 여성: 'F'로 구분", example = "M") + private String sex; + + @Schema(description = "생년월일(Date of Birth) - YYYYMMDD 형식", example = "19900101") + private String birthDate; + + @Schema(description = "신장(Height) - 단위: cm", example = "175.0") + private Float height; + + @Schema(description = "체중(Weight) - 단위: kg", example = "70.5") + private Float weight; + } }