diff --git a/src/main/java/com/back/domain/chatbot/service/ChatbotService.java b/src/main/java/com/back/domain/chatbot/service/ChatbotService.java index 6c6b55d0..6add7469 100644 --- a/src/main/java/com/back/domain/chatbot/service/ChatbotService.java +++ b/src/main/java/com/back/domain/chatbot/service/ChatbotService.java @@ -465,13 +465,14 @@ private StepRecommendationResponseDto getFinalRecommendations( ); List recommendations = cocktailPage.getContent().stream() - .map(cocktail -> new CocktailSummaryResponseDto( - cocktail.getId(), - cocktail.getCocktailName(), - cocktail.getCocktailImgUrl(), - cocktail.getAlcoholStrength() - )) - .collect(Collectors.toList()); + .map(cocktail -> new CocktailSummaryResponseDto( + cocktail.getId(), + cocktail.getCocktailName(), + cocktail.getCocktailNameKo(), + cocktail.getCocktailImgUrl(), + cocktail.getAlcoholStrength().getDescription() + )) + .collect(Collectors.toList()); // 추천 이유는 각 칵테일별 설명으로 들어가도록 유도 String stepTitle = recommendations.isEmpty() diff --git a/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java b/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java index 8693c615..4bf7570f 100644 --- a/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java +++ b/src/main/java/com/back/domain/cocktail/controller/CocktailShareController.java @@ -1,42 +1,36 @@ package com.back.domain.cocktail.controller; -import com.back.domain.cocktail.repository.CocktailRepository; +import com.back.domain.cocktail.dto.CocktailShareResponseDto; +import com.back.domain.cocktail.entity.Cocktail; +import com.back.domain.cocktail.service.CocktailService; import com.back.global.rsData.RsData; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; -import java.util.Map; - @RestController @RequestMapping("/cocktails") @RequiredArgsConstructor public class CocktailShareController { - private final CocktailRepository cocktailRepository; + private final CocktailService cocktailService; @Value("${custom.prod.frontUrl}") private String frontUrl; @GetMapping("/{id}/share") - public ResponseEntity>> getShareLink(@PathVariable Long id) { - return cocktailRepository.findById(id) - .map(cocktail -> { - Map response = Map.of( - // 공유 URL - "url", frontUrl +"/cocktails/" + cocktail.getId(), - // 공유 제목 - "title", cocktail.getCocktailName(), - // 공유 이미지 (선택) - "imageUrl", cocktail.getCocktailImgUrl() - ); - return ResponseEntity.ok(RsData.successOf(response)); - }) - .orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND) - .body(RsData.failOf("칵테일을 찾을 수 없습니다."))); + public ResponseEntity> getShareLink(@PathVariable Long id) { + Cocktail cocktail = cocktailService.getCocktailById(id); + + CocktailShareResponseDto responseDto = new CocktailShareResponseDto( + frontUrl + "/cocktails/" + cocktail.getId(), + cocktail.getCocktailNameKo(), + cocktail.getCocktailImgUrl() + ); + + return ResponseEntity.ok(RsData.successOf(responseDto)); } } diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailDetailResponseDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailResponseDto.java index 0f8d73d8..4bed9cc2 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailDetailResponseDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailDetailResponseDto.java @@ -1,52 +1,15 @@ package com.back.domain.cocktail.dto; -import com.back.domain.cocktail.entity.Cocktail; -import com.back.domain.cocktail.enums.AlcoholBaseType; -import com.back.domain.cocktail.enums.AlcoholStrength; -import com.back.domain.cocktail.enums.CocktailType; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Getter -@NoArgsConstructor -public class CocktailDetailResponseDto { - private Long cocktailId; - private String cocktailName; - private AlcoholStrength alcoholStrength; - private CocktailType cocktailType; - private AlcoholBaseType alcoholBaseType; - private String cocktailImgUrl; - private String cocktailStory; - private String ingredient; - private String recipe; - - public CocktailDetailResponseDto( - long cocktailId, String cocktailName, - AlcoholStrength alcoholStrength, CocktailType cocktailType, - AlcoholBaseType alcoholBaseType, String cocktailImgUrl, - String cocktailStory, String ingredient, - String recipe - ) { - this.cocktailId = cocktailId; - this.cocktailName = cocktailName; - this.alcoholStrength = alcoholStrength; - this.cocktailType = cocktailType; - this.alcoholBaseType = alcoholBaseType; - this.cocktailImgUrl = cocktailImgUrl; - this.cocktailStory = cocktailStory; - this.ingredient = ingredient; - this.recipe = recipe; - } - - public CocktailDetailResponseDto(Cocktail cocktail) { - this.cocktailId = cocktail.getId(); - this.cocktailName = cocktail.getCocktailName(); - this.alcoholStrength = cocktail.getAlcoholStrength(); - this.cocktailType = cocktail.getCocktailType(); - this.alcoholBaseType = cocktail.getAlcoholBaseType(); - this.cocktailImgUrl = cocktail.getCocktailImgUrl(); - this.cocktailStory = cocktail.getCocktailStory(); - this.ingredient = cocktail.getIngredient(); - this.recipe = cocktail.getRecipe(); - } +public record CocktailDetailResponseDto( + Long cocktailId, + String cocktailName, + String cocktailNameKo, + String alcoholStrength, + String cocktailType, + String alcoholBaseType, + String cocktailImgUrl, + String cocktailStory, + String ingredient, + String recipe +) { } diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailSearchResponseDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailSearchResponseDto.java index 641f033e..06078a19 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailSearchResponseDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailSearchResponseDto.java @@ -1,14 +1,9 @@ package com.back.domain.cocktail.dto; -import com.back.domain.cocktail.enums.AlcoholBaseType; -import com.back.domain.cocktail.enums.AlcoholStrength; -import com.back.domain.cocktail.enums.CocktailType; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; -import java.time.LocalDateTime; - @Getter @Setter @NoArgsConstructor @@ -16,24 +11,24 @@ public class CocktailSearchResponseDto { private long cocktailId; private String cocktailName; - private AlcoholStrength alcoholStrength; - private CocktailType cocktailType; - private AlcoholBaseType alcoholBaseType; + private String cocktailNameKo; + private String alcoholStrength; + private String cocktailType; + private String alcoholBaseType; private String cocktailImgUrl; private String cocktailStory; - private LocalDateTime createdAt; - public CocktailSearchResponseDto(long cocktailId, String cocktailName, - AlcoholStrength alcoholStrength, CocktailType cocktailType, - AlcoholBaseType alcoholBaseType, String cocktailImgUrl, - String cocktailStory, LocalDateTime createdAt) { + public CocktailSearchResponseDto(long cocktailId, String cocktailName, String cocktailNameKo, + String alcoholStrength, String cocktailType, + String alcoholBaseType, String cocktailImgUrl, + String cocktailStory) { this.cocktailId = cocktailId; this.cocktailName = cocktailName; + this.cocktailNameKo = cocktailNameKo; this.alcoholStrength = alcoholStrength; this.cocktailType = cocktailType; this.alcoholBaseType = alcoholBaseType; this.cocktailImgUrl = cocktailImgUrl; this.cocktailStory = cocktailStory; - this.createdAt = createdAt; } } \ No newline at end of file diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailShareResponseDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailShareResponseDto.java new file mode 100644 index 00000000..362b9d46 --- /dev/null +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailShareResponseDto.java @@ -0,0 +1,14 @@ +package com.back.domain.cocktail.dto; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +public class CocktailShareResponseDto { + private String url; + private String title; + private String imageUrl; +} diff --git a/src/main/java/com/back/domain/cocktail/dto/CocktailSummaryResponseDto.java b/src/main/java/com/back/domain/cocktail/dto/CocktailSummaryResponseDto.java index 24805596..70633d71 100644 --- a/src/main/java/com/back/domain/cocktail/dto/CocktailSummaryResponseDto.java +++ b/src/main/java/com/back/domain/cocktail/dto/CocktailSummaryResponseDto.java @@ -1,19 +1,21 @@ package com.back.domain.cocktail.dto; -import com.back.domain.cocktail.enums.AlcoholStrength; -import lombok.Getter; +import com.back.domain.cocktail.entity.Cocktail; -@Getter -public class CocktailSummaryResponseDto { - private Long cocktailId; - private String cocktailName; - private String cocktailImgUrl; - private AlcoholStrength alcoholStrength; - - public CocktailSummaryResponseDto(Long id, String name, String imageUrl, AlcoholStrength alcoholStrength) { - this.cocktailId = id; - this.cocktailName = name; - this.cocktailImgUrl = imageUrl; - this.alcoholStrength = alcoholStrength; +public record CocktailSummaryResponseDto( + Long cocktailId, + String cocktailName, + String cocktailNameKo, + String cocktailImgUrl, + String alcoholStrength // Enum 대신 String +) { + public CocktailSummaryResponseDto(Cocktail cocktail) { + this( + cocktail.getId(), + cocktail.getCocktailName(), + cocktail.getCocktailNameKo(), + cocktail.getCocktailImgUrl(), + cocktail.getAlcoholStrength().getDescription() // 설명으로 변환 + ); } -} +} \ No newline at end of file diff --git a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java index a9420762..d55b6518 100644 --- a/src/main/java/com/back/domain/cocktail/entity/Cocktail.java +++ b/src/main/java/com/back/domain/cocktail/entity/Cocktail.java @@ -7,6 +7,7 @@ import lombok.*; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @@ -20,6 +21,7 @@ @Builder @ToString @Entity +@EntityListeners(AuditingEntityListener.class) public class Cocktail { @Id @GeneratedValue(strategy = IDENTITY) diff --git a/src/main/java/com/back/domain/cocktail/service/CocktailService.java b/src/main/java/com/back/domain/cocktail/service/CocktailService.java index 1a36f507..d3042b87 100644 --- a/src/main/java/com/back/domain/cocktail/service/CocktailService.java +++ b/src/main/java/com/back/domain/cocktail/service/CocktailService.java @@ -18,6 +18,7 @@ import org.springframework.util.CollectionUtils; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.stream.Collectors; @@ -51,7 +52,7 @@ public List getCocktails (Long lastId, Integer size) cocktails = cocktailRepository.findByIdLessThanOrderByIdDesc(lastId, PageRequest.of(0, fetchSize)); } return cocktails.stream() - .map(c -> new CocktailSummaryResponseDto(c.getId(), c.getCocktailName(), c.getCocktailImgUrl(), c.getAlcoholStrength())) + .map(c -> new CocktailSummaryResponseDto(c.getId(), c.getCocktailName(), c.getCocktailNameKo(), c.getCocktailImgUrl(), c.getAlcoholStrength().getDescription())) .collect(Collectors.toList()); } @@ -108,12 +109,12 @@ public List searchAndFilter (CocktailSearchRequestDto .map(c -> new CocktailSearchResponseDto( c.getId(), c.getCocktailName(), - c.getAlcoholStrength(), - c.getCocktailType(), - c.getAlcoholBaseType(), + c.getCocktailNameKo(), + c.getAlcoholStrength().getDescription(), + c.getCocktailType().getDescription(), + c.getAlcoholBaseType().getDescription(), c.getCocktailImgUrl(), - c.getCocktailStory(), - c.getCreatedAt() + c.getCocktailStory() )) .collect(Collectors.toList()); @@ -124,11 +125,50 @@ public List searchAndFilter (CocktailSearchRequestDto // return CollectionUtils.isEmpty(list) ? null : list; // } - // 칵테일 상세조회 - @Transactional(readOnly = true) - public CocktailDetailResponseDto getCocktailDetailById (Long cocktailId){ - Cocktail cocktail = cocktailRepository.findById(cocktailId) - .orElseThrow(() -> new NoSuchElementException("칵테일을 찾을 수 없습니다. id: " + cocktailId)); - return new CocktailDetailResponseDto(cocktail); + // 칵테일 상세조회 + @Transactional(readOnly = true) + public CocktailDetailResponseDto getCocktailDetailById(Long cocktailId) { + Cocktail cocktail = cocktailRepository.findById(cocktailId) + .orElseThrow(() -> new NoSuchElementException("칵테일을 찾을 수 없습니다. id: " + cocktailId)); + + // ingredient 분수 변환 + String formattedIngredient = convertFractions(cocktail.getIngredient()); + + return new CocktailDetailResponseDto( + cocktail.getId(), + cocktail.getCocktailName(), + cocktail.getCocktailNameKo(), + cocktail.getAlcoholStrength().getDescription(), + cocktail.getCocktailType().getDescription(), + cocktail.getAlcoholBaseType().getDescription(), + cocktail.getCocktailImgUrl(), + cocktail.getCocktailStory(), + formattedIngredient, + cocktail.getRecipe() + ); + } + + private String convertFractions(String ingredient) { + if (ingredient == null) return null; + + // 치환 테이블 생성 + Map fractionMap = Map.of( + "1/2", "½", + "1/3", "⅓", + "2/3", "⅔", + "1/4", "¼", + "3/4", "¾", + "1/8", "⅛", + "3/8", "⅜", + "5/8", "⅝", + "7/8", "⅞" + ); + + // 테이블 기반 치환 + for (Map.Entry entry : fractionMap.entrySet()) { + ingredient = ingredient.replace(entry.getKey(), entry.getValue()); } + + return ingredient; } +} diff --git a/src/main/java/com/back/domain/cocktail/service/RecommendService.java b/src/main/java/com/back/domain/cocktail/service/RecommendService.java index 0d8e2681..32d5a690 100644 --- a/src/main/java/com/back/domain/cocktail/service/RecommendService.java +++ b/src/main/java/com/back/domain/cocktail/service/RecommendService.java @@ -37,8 +37,8 @@ public List recommendRelatedCocktails(Long cocktai c.getCocktailNameKo(), c.getCocktailName(), c.getCocktailImgUrl(), - c.getAlcoholStrength().name(), - c.getAlcoholBaseType().name() + c.getAlcoholStrength().getDescription(), + c.getAlcoholBaseType().getDescription() )) .toList(); } diff --git a/src/main/java/com/back/global/standard/util/FractionFinder.java b/src/main/java/com/back/global/standard/util/FractionFinder.java new file mode 100644 index 00000000..fb59d7e5 --- /dev/null +++ b/src/main/java/com/back/global/standard/util/FractionFinder.java @@ -0,0 +1,40 @@ +package com.back.global.standard.util; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class FractionFinder { + + public static void main(String[] args) { + try { + // 1️⃣ SQL 파일 경로 설정 + Path path = Paths.get("src/main/resources/cocktails.csv"); + + // 2️⃣ 파일 읽기 + String content = Files.readString(path); + + // 3️⃣ 분수 패턴 정의 (예: 1/2, 3/4 등) + Pattern pattern = Pattern.compile("\\d/\\d"); // 공백/문자 붙어 있어도 매칭 + Matcher matcher = pattern.matcher(content); + + // 4️⃣ 분수 출력 + boolean found = false; + while (matcher.find()) { + System.out.println("찾은 분수: " + matcher.group()); + found = true; + } + + if (!found) { + System.out.println("SQL 파일에 분수 표현이 없습니다."); + } + + } catch (IOException e) { + System.err.println("SQL 파일을 읽는 중 오류 발생: " + e.getMessage()); + e.printStackTrace(); + } + } +} diff --git a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java index 0ad94224..c830e0cc 100644 --- a/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java +++ b/src/test/java/com/back/domain/cocktail/controller/CocktailControllerTest.java @@ -79,9 +79,9 @@ void t1() throws Exception { .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.message").value("success")) .andExpect(jsonPath("$.data.cocktailName").value("모히토")) - .andExpect(jsonPath("$.data.alcoholStrength").value("WEAK")) - .andExpect(jsonPath("$.data.cocktailType").value("SHORT")) - .andExpect(jsonPath("$.data.alcoholBaseType").value("RUM")); + .andExpect(jsonPath("$.data.alcoholStrength").value("약한 도수 (1~5%)")) + .andExpect(jsonPath("$.data.cocktailType").value("숏")) + .andExpect(jsonPath("$.data.alcoholBaseType").value("럼")); } @Test @@ -177,9 +177,9 @@ void t5() throws Exception { .andExpect(jsonPath("$.code").value(200)) .andExpect(jsonPath("$.message").value("success")) .andExpect(jsonPath("$.data[0].cocktailName").value("모히토")) - .andExpect(jsonPath("$.data[0].alcoholStrength").value("WEAK")) - .andExpect(jsonPath("$.data[0].cocktailType").value("SHORT")) - .andExpect(jsonPath("$.data[0].alcoholBaseType").value("RUM")); + .andExpect(jsonPath("$.data[0].alcoholStrength").value("약한 도수 (1~5%)")) + .andExpect(jsonPath("$.data[0].cocktailType").value("숏")) + .andExpect(jsonPath("$.data[0].alcoholBaseType").value("럼")); } @TestConfiguration diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml index aa7991e1..e126dad9 100644 --- a/src/test/resources/application-test.yml +++ b/src/test/resources/application-test.yml @@ -1,6 +1,14 @@ spring: - profiles: - active: test + # 테스트용 AWS 프로퍼티 추가 + cloud: + aws: + credentials: + access-key: test-access-key + secret-key: test-secret-key + region: + static: ap-northeast-2 + s3: + bucket: test-bucket-name # H2 테스트 데이터베이스 datasource: