Spring/[P] AI 기반 사용자 맞춤형 메뉴와 맛집 추천

[Springboot] 식사 통계 조회 개발하기

alsruds 2024. 9. 4. 23:53

📂 apiPayload

📂 config

📂 controller

  L MainController

📂 domain

  L 📂 common

  L 📂 enums

  L User

  L Food

📂 dto

  L 📂 request

  L 📂 response

        L MainStatisticsResponseDto

        L MainStatisticsResponseListDto

📂 jwt

📂 repository

  L UserRepository

  L FoodRepository

📂 service

  L MainService

  L MainServiceImpl

 

 

날짜별로 칼로리, 탄수화물량, 단백질량, 지방량 정보를 확인할 수 있도록 전달하자

 

MainStatisticsResponseListDto : 날짜별로 데이터를 묶어준다

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MainStatisticsResponseListDto {
    private List<MainStatisticsResponseDto> data;

    public static MainStatisticsResponseListDto mainStatisticsResponseList(List<MainStatisticsResponseDto> dtoList, List<LocalDate> allDates) {
        // 날짜별로 데이터를 맵핑
        Map<LocalDate, MainStatisticsResponseDto> dtoMap = dtoList.stream()
                .collect(Collectors.toMap(MainStatisticsResponseDto::getDate, dto -> dto));

        // 모든 날짜에 대해 데이터가 없으면 기본값 생성
        List<MainStatisticsResponseDto> fullDtoList = allDates.stream()
                .map(date -> dtoMap.getOrDefault(date, MainStatisticsResponseDto.createWithDefaults(date)))
                .toList();

        return MainStatisticsResponseListDto.builder()
                .data(fullDtoList)
                .build();
    }
}

 

MainStatisticsResponseDto : 전달하려는 데이터 빌드 & 기본값 설정

@Getter
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class MainStatisticsResponseDto {
    private LocalDate date;
    private int carbohydrate;
    private int protein;
    private int fat;
    private int kcal;

    public static List<MainStatisticsResponseDto> mainStatisticsResponse(List<Food> foodList) {
        return foodList.stream()
                .map(m -> MainStatisticsResponseDto.builder()
                        .date(m.getCreatedAt())
                        .carbohydrate(m.getCarbohydrate())
                        .protein(m.getProtein())
                        .fat(m.getFat())
                        .kcal((m.getCarbohydrate() * 4) + (m.getProtein() * 4) + (m.getFat() * 9))
                        .build())
                .collect(Collectors.toList());
    }

    public static MainStatisticsResponseDto createWithDefaults(LocalDate date) {
        return MainStatisticsResponseDto.builder()
                .date(date)
                .carbohydrate(0)
                .protein(0)
                .fat(0)
                .kcal(0)
                .build();
    }
}

 

MainController : 파라미터로 시작일과 종료일을 받아 해당 날짜에 해당하는 데이터를 전달할 수 있도록 한다

@RestController
@RequiredArgsConstructor
@RequestMapping("/main")
public class MainController {

    private final MainService mainService;

    @GetMapping("/statistics") // 통계 조회
    public ApiResponse<MainStatisticsResponseListDto> getStatistics(@RequestHeader("Authorization") String token,
                                                                    @RequestParam("startDate") String startDate,
                                                                    @RequestParam("endDate") String endDate) {
        return ApiResponse.onSuccess(mainService.getStatistics(extractUserEmail(token), startDate, endDate));
    }

    public String extractUserEmail(String token) {
        String jwtToken = token.substring(7);
        String userEmail = JwtUtil.getEmail(jwtToken);
        return userEmail;
    }
}

 

MainServiceImpl

  L String 으로 받은 날짜를 LocalDate 로 변환해주어야 한다

@Service
@Transactional
@RequiredArgsConstructor
public class MainServiceImpl implements MainService {

    private final UserRepository userRepository;
    private final FoodRepository foodRepository;

    @Override
    public MainStatisticsResponseListDto getStatistics(String userEmail, String startDate, String endDate) {
        // 사용자 존재 여부 확인
        User user = checkUser(userEmail);

        // 날짜 변환
        LocalDate startLocalDate = LocalDate.parse(startDate);
        LocalDate endLocalDate = LocalDate.parse(endDate);

        // 사용자 - 날짜에 해당하는 음식 통계 조회
        List<Food> foodList = foodRepository.findAllByUserAndCreatedAtBetween(user, startLocalDate, endLocalDate);
        List<MainStatisticsResponseDto> dtoList = MainStatisticsResponseDto.mainStatisticsResponse(foodList);

        // 시작 날짜부터 끝 날짜까지 모든 날짜 리스트 생성
        List<LocalDate> allDates = startLocalDate.datesUntil(endLocalDate.plusDays(1)).toList();

        return MainStatisticsResponseListDto.mainStatisticsResponseList(dtoList, allDates);
    }

    public User checkUser(String userEmail) {
        return userRepository.findByEmail(userEmail)
                .orElseThrow(() -> new GeneralException(ErrorStatus.MEMBER_NOT_FOUND));
    }
}

 


2024.09.03 - [Spring/[P] AI 기반 사용자 맞춤형 메뉴와 맛집 추천] - [Springboot] 식사 통계 조회 설계하기

 

[Springboot] 식사 통계 조회 설계하기

📂 /main  L 기록 조회   L 기록 등록  L 통계 조회 ⬅️⬅️⬅️   🔧 디자인  🔧 필요한 데이터  L 조회하는 날짜 기간 (시작 날짜 & 끝 날짜) 🔧 HTTP Method  L GET🔧 API Path  L /main/statistics?st

alsrudalsrudalsrud.tistory.com