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 { +} 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; + } } 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