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
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
Expand All @@ -11,12 +12,11 @@
import lombok.RequiredArgsConstructor;
import nerdinary.hackathon.domain.food.dto.FoodRegisterRequest;
import nerdinary.hackathon.domain.food.dto.FoodRegisterResponse;
import nerdinary.hackathon.domain.food.dto.FoodSearchResponse;
import nerdinary.hackathon.domain.food.service.FoodService;
import nerdinary.hackathon.domain.login.jwt.JwtValidation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;

@RestController
@RequiredArgsConstructor
Expand All @@ -29,6 +29,9 @@ public class FoodController {
@Operation(
summary = "음식 등록",
description = "사용자가 음식을 등록합니다.",
parameters = {
@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true)
},
responses = {
@ApiResponse(responseCode = "200", description = "등록 성공",
content = @Content(schema = @Schema(implementation = FoodRegisterResponse.class))),
Expand All @@ -37,12 +40,33 @@ public class FoodController {
)
@PostMapping("/register")
public ResponseEntity<FoodRegisterResponse> registerFood(
HttpServletRequest request,
@Parameter(hidden = true) @JwtValidation Long userId,
@Parameter(description = "음식 등록 정보", required = true, schema = @Schema(implementation = FoodRegisterRequest.class))
@RequestBody @Valid FoodRegisterRequest dto
) {
Long userId = (Long) request.getAttribute("userId");
FoodRegisterResponse response = foodService.registerFood(dto, userId);
return ResponseEntity.ok(response);
}

@Operation(
summary = "음식 검색",
description = "음식이름을 검색하면 자신이 등록한 음식들을 반환합니다.",
parameters = {
@Parameter(name = "Authorization", in = ParameterIn.HEADER, required = true),
@Parameter(name = "name", description = "검색어", required = true)
},
responses = {
@ApiResponse(responseCode = "200", description = "검색 성공",
content = @Content(schema = @Schema(implementation = FoodSearchResponse.class))),
@ApiResponse(responseCode = "400", description = "잘못된 요청")
}
)
@GetMapping("/search")
public ResponseEntity<FoodSearchResponse> searchFood(
@Parameter(hidden = true) @JwtValidation Long userId,
@RequestParam String query
) {
FoodSearchResponse response = foodService.searchFood(userId, query);
return ResponseEntity.ok(response);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package nerdinary.hackathon.domain.food.dto;

import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDate;
import java.util.List;

@Getter
@AllArgsConstructor
public class FoodSearchResponse {
private List<FoodSearchResultDto> results;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package nerdinary.hackathon.domain.food.dto;


import lombok.AllArgsConstructor;
import lombok.Getter;

import java.time.LocalDate;

@Getter
@AllArgsConstructor
public class FoodSearchResultDto {
private Long foodRegisterId;
private String foodName;
private LocalDate expirationDate;
private Long remainingDays;
}

Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,7 @@ public interface FoodRegisterRepository extends JpaRepository<FoodRegister, Long

// 유통기한이 지난 음식 조회
List<FoodRegister> findByUserAndExpirationDateBeforeAndFoodStatusIsTrue(User user, java.time.LocalDate now);

// 특정사용자가 음식이름 조회
List<FoodRegister> findByUserAndFood_FoodNameContainingIgnoreCase(User user, String foodName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import nerdinary.hackathon.domain.food.dto.FoodRegisterRequest;
import nerdinary.hackathon.domain.food.dto.FoodRegisterResponse;
import nerdinary.hackathon.domain.food.dto.FoodSearchResponse;

public interface FoodService {

FoodRegisterResponse registerFood(FoodRegisterRequest request, Long userId);
FoodSearchResponse searchFood(Long userId, String query);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import lombok.RequiredArgsConstructor;
import nerdinary.hackathon.domain.food.dto.FoodRegisterRequest;
import nerdinary.hackathon.domain.food.dto.FoodRegisterResponse;
import nerdinary.hackathon.domain.food.dto.FoodSearchResponse;
import nerdinary.hackathon.domain.food.dto.FoodSearchResultDto;
import nerdinary.hackathon.domain.food.entity.Food;
import nerdinary.hackathon.domain.food.entity.FoodRegister;
import nerdinary.hackathon.domain.food.repository.FoodRegisterRepository;
Expand All @@ -16,6 +18,7 @@
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

@Service
Expand Down Expand Up @@ -64,4 +67,27 @@ public FoodRegisterResponse registerFood(FoodRegisterRequest request, Long userI

return new FoodRegisterResponse(register.getFoodRegisterId(), food.getFoodName(), expirationDate);
}

@Override
@Transactional
public FoodSearchResponse searchFood(Long userId, String query){
User user = userRepository.findById(userId)
.orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));

List<FoodRegister> foodRegisters = foodRegisterRepository
.findByUserAndFood_FoodNameContainingIgnoreCase(user, query);

List<FoodSearchResultDto> results = foodRegisters.stream()
.map(fr -> new FoodSearchResultDto(
fr.getFoodRegisterId(),
fr.getFood().getFoodName(),
fr.getExpirationDate(),
fr.getExpirationDate() != null && fr.getPurchaseDate() != null
? (long) fr.getExpirationDate().toEpochDay() - fr.getPurchaseDate().toEpochDay()
: null
))
.toList();

return new FoodSearchResponse(results);
}
}