From 97cba9ce41aa3980af4f95a1e6203fa09d171221 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 28 Dec 2023 04:20:18 +0900 Subject: [PATCH 01/25] =?UTF-8?q?[FEAT]=20#3=20ChatGPT=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 단답 확인 과정 테스트 --- .../chatgpt/application/ChatGptService.java | 72 +++++++++++++++++++ .../domain/chatgpt/config/ChatgptConfig.java | 34 +++++++++ .../presentation/ChatGptController.java | 44 ++++++++++++ 3 files changed, 150 insertions(+) create mode 100644 src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java create mode 100644 src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java create mode 100644 src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java diff --git a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java new file mode 100644 index 0000000..f5d1caa --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java @@ -0,0 +1,72 @@ +package com.finfellows.domain.chatgpt.application; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.finfellows.domain.chatgpt.config.ChatgptConfig; +import com.finfellows.domain.chatgpt.domain.ChatGptMessage; +import com.finfellows.domain.chatgpt.dto.ChatgptQuestionRequest; +import com.finfellows.domain.chatgpt.dto.ChatgptRequest; +import io.github.flashvayne.chatgpt.service.ChatgptService; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Service; +import org.springframework.web.reactive.function.client.WebClient; +import reactor.core.publisher.Flux; +import java.util.*; + +@Service +@RequiredArgsConstructor +public class ChatGptService { + + // 라이브러리 제공 + private final ChatgptService chatgptService; + + @Value("${GPT_Token}") + private String apiKey; + private final ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE ); + public Flux ask(ChatgptQuestionRequest chatGptQuestionRequest) throws JsonProcessingException { + WebClient client = WebClient.builder() + .baseUrl(ChatgptConfig.CHAT_URL) + .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) + .defaultHeader(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey) + .build(); + + List messages = new ArrayList<>(); + messages.add(ChatGptMessage.builder() + .role(ChatgptConfig.ROLE) + .content(chatGptQuestionRequest.getQuestion()) + .build()); + + ChatgptRequest chatGptRequest = new ChatgptRequest( + ChatgptConfig.CHAT_MODEL, + ChatgptConfig.MAX_TOKEN, + ChatgptConfig.TEMPERATURE, + ChatgptConfig.STREAM_TRUE, + messages + ); + + String requestValue = objectMapper.writeValueAsString(chatGptRequest); + + Flux eventStream = client.post() + .bodyValue(requestValue) + .accept(MediaType.TEXT_EVENT_STREAM) + .retrieve() + .bodyToFlux(String.class); + + return eventStream; + } + + // 단답 답변 + public String getChatResponse(String prompt) { + System.out.print(apiKey); + // ChatGPT에 질문 전송 + return chatgptService.sendMessage(prompt); + } +} + diff --git a/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java b/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java new file mode 100644 index 0000000..f795a60 --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java @@ -0,0 +1,34 @@ +package com.finfellows.domain.chatgpt.config; + +import com.theokanning.openai.OpenAiService; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.time.Duration; + +@Slf4j +@Configuration +public class ChatgptConfig { + public static final String AUTHORIZATION = "Authorization"; + public static final String BEARER = "Bearer "; + public static final String CHAT_MODEL = "gpt-3.5-turbo"; + public static final Integer MAX_TOKEN = 300; + public static final Boolean STREAM_TRUE = true; + public static final Boolean STREAM_FALSE = false; + public static final String ROLE = "user"; + public static final Double TEMPERATURE = 0.6; + public static final String MEDIA_TYPE = "application/json; charset=UTF-8"; + public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions"; + + @Value("${GPT_Token}") + private String token; + + @Bean + public OpenAiService openAiService() { + log.info("token: {}을 활용한 OpenApiService를 생성합니다!", token); + return new OpenAiService(token, Duration.ofSeconds(60)); + } +} diff --git a/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java new file mode 100644 index 0000000..ba8343e --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java @@ -0,0 +1,44 @@ +package com.finfellows.domain.chatgpt.presentation; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.finfellows.domain.chatgpt.application.ChatGptService; +import com.finfellows.domain.chatgpt.dto.ChatgptQuestionRequest; +import jakarta.servlet.http.*; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.MediaType; +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 reactor.core.publisher.Flux; + +import java.util.*; + +@RestController +@RequestMapping("/api/v1/chat-gpt") +@RequiredArgsConstructor +@Slf4j +public class ChatGptController { + private final ChatGptService chatgptService; + +// @PostMapping(value="/ask-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) +// public Flux ask(Locale locale, +// HttpServletRequest request, +// HttpServletResponse response, +// @RequestBody ChatgptQuestionRequest chatGptQuestionRequest){ +// try { +// return chatgptService.ask(chatGptQuestionRequest); +// }catch (JsonProcessingException je){ +// log.error(je.getMessage()); +// return Flux.empty(); +// } +// } + + // 단답 테스트 + // https://yjkim-dev.tistory.com/56 + @PostMapping("") + public String test(@RequestBody String question) { + return chatgptService.getChatResponse(question); + } +} \ No newline at end of file From edcfb728c5b5d7d8921c693efbc8f62036e367e9 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 28 Dec 2023 04:23:45 +0900 Subject: [PATCH 02/25] =?UTF-8?q?[FIX]=20#3=20SecurityConfig=20permitAll?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/config/security/SecurityConfig.java | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/finfellows/global/config/security/SecurityConfig.java b/src/main/java/com/finfellows/global/config/security/SecurityConfig.java index b12190e..b2a5b83 100644 --- a/src/main/java/com/finfellows/global/config/security/SecurityConfig.java +++ b/src/main/java/com/finfellows/global/config/security/SecurityConfig.java @@ -6,6 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration; @@ -20,8 +21,6 @@ import static org.springframework.security.config.Customizer.*; - - @RequiredArgsConstructor @Configuration @EnableWebSecurity @@ -58,13 +57,22 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .permitAll() .requestMatchers("/swagger", "/swagger-ui.html", "/swagger-ui/**", "/api-docs", "/api-docs/**", "/v3/api-docs/**") .permitAll() - .requestMatchers("/login/**", "/auth/**", "/oauth2/**") + .requestMatchers("/login/**", "/auth/**", "/oauth2/**", "api/**") .permitAll() .requestMatchers("/blog/**") .permitAll() + + .requestMatchers(HttpMethod.POST, "https://api.openai.com/v1/completions") + .permitAll() + + .requestMatchers("/api/v1/chat-gpt") + .permitAll() + .anyRequest() .authenticated()); + + http.addFilterBefore(customOncePerRequestFilter(), UsernamePasswordAuthenticationFilter.class); return http.build(); } From 2976c86908c5e985d6f0ba0d63b8c55ee86aa785 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 28 Dec 2023 04:30:05 +0900 Subject: [PATCH 03/25] =?UTF-8?q?[FEAT]=20#3=20ChatgptRequest=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GPT Request DTO format --- .../domain/chatgpt/dto/ChatgptRequest.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java diff --git a/src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java b/src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java new file mode 100644 index 0000000..6bb229e --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java @@ -0,0 +1,37 @@ +package com.finfellows.domain.chatgpt.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.finfellows.domain.chatgpt.domain.ChatGptMessage; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; +import java.util.*; + +@Getter +@NoArgsConstructor +//chatGPT에 요청할 DTO Format +public class ChatgptRequest implements Serializable { + private String model; + @JsonProperty("max_tokens") + private Integer maxTokens; + private Double temperature; + private Boolean stream; + private List messages; + + //@JsonProperty("top_p") + //private Double topP; + + @Builder + public ChatgptRequest(String model, Integer maxTokens, Double temperature, + Boolean stream, List messages + /*,Double topP*/) { + this.model = model; + this.maxTokens = maxTokens; + this.temperature = temperature; + this.stream = stream; + this.messages = messages; + //this.topP = topP; + } +} From ee7c8f2b483270574991706130f9a75219fc3c03 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 28 Dec 2023 12:18:44 +0900 Subject: [PATCH 04/25] =?UTF-8?q?[FIX]=20#3=20Chatgpt=20dependencies=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build.gradle b/build.gradle index 44597da..39a0e21 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,13 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-web' + //gpt + implementation group: 'com.theokanning.openai-gpt3-java', name: 'client', version: '0.9.0' + implementation 'io.github.flashvayne:chatgpt-spring-boot-starter:1.0.4' + + //webflux + implementation 'org.springframework.boot:spring-boot-starter-webflux' + compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.h2database:h2' runtimeOnly 'com.mysql:mysql-connector-j' From 58027f657b8d1c94e321aa40ba1c17bef4a70f28 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Fri, 29 Dec 2023 08:56:57 +0900 Subject: [PATCH 05/25] =?UTF-8?q?[FEAT]=20#14=20EduContent=20DTO=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/educontent/domain/EduContent.java | 14 +++++++------- .../educontent/dto/request/EduContentRequest.java | 13 +++++++++++++ .../dto/response/EduContentResponse.java | 13 +++++++++++++ 3 files changed, 33 insertions(+), 7 deletions(-) create mode 100644 src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java create mode 100644 src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java diff --git a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java index 97b6fef..2317b99 100644 --- a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java +++ b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java @@ -21,19 +21,19 @@ public class EduContent extends BaseEntity { private Long id; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name="id") - private Post post_id; + @JoinColumn(name="post_id") + private Post post; - @Column(name="sequence", nullable = false) - private Long sequence; + @Column(name="title") + private String title; @Column(name="content") private String content; @Builder - public EduContent(Post post_id, Long sequence, String content){ - this.post_id=post_id; - this.sequence=sequence; + public EduContent(Post post, String title, String content){ + this.post=post; + this.title=title; this.content=content; } } diff --git a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java new file mode 100644 index 0000000..77ab2c4 --- /dev/null +++ b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java @@ -0,0 +1,13 @@ +package com.finfellows.domain.educontent.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class EduContentRequest { + private String title; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java new file mode 100644 index 0000000..849f310 --- /dev/null +++ b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java @@ -0,0 +1,13 @@ +package com.finfellows.domain.educontent.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class EduContentResponse { + private String title; + private String content; +} From 3cf2fc603e4cb4822dd2f5abfdb4678a43090b40 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Fri, 29 Dec 2023 08:57:57 +0900 Subject: [PATCH 06/25] =?UTF-8?q?[FIX]=20#14=20Post=20AccessLevel=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/finfellows/domain/post/domain/Post.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/finfellows/domain/post/domain/Post.java b/src/main/java/com/finfellows/domain/post/domain/Post.java index 6b9e988..5231c18 100644 --- a/src/main/java/com/finfellows/domain/post/domain/Post.java +++ b/src/main/java/com/finfellows/domain/post/domain/Post.java @@ -11,7 +11,7 @@ @Entity @Table(name="Post") -@NoArgsConstructor(access = AccessLevel.PROTECTED) +@NoArgsConstructor(access = AccessLevel.PUBLIC) @Getter @Where(clause = "status = 'ACTIVE'") public class Post extends BaseEntity { From cf2d039ddf04f24c054b8d1ed46b9f990a0b38a8 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Fri, 29 Dec 2023 08:59:24 +0900 Subject: [PATCH 07/25] =?UTF-8?q?[FEAT]=20#14=20educontent=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/EduContentService.java | 32 +++++++++++++++++++ .../repository/EduContentRepository.java | 3 +- .../presentation/EduContentController.java | 24 ++++++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/finfellows/domain/educontent/application/EduContentService.java create mode 100644 src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java new file mode 100644 index 0000000..e71b7ed --- /dev/null +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -0,0 +1,32 @@ +package com.finfellows.domain.educontent.application; + +import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.domain.repository.EduContentRepository; +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import com.finfellows.domain.post.domain.Post; +import com.finfellows.domain.post.domain.repository.PostRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class EduContentService { + private final EduContentRepository eduContentRepository; + private final PostRepository postRepository; + public EduContent createEduContent(EduContentResponse request) { + Post post = new Post(); + postRepository.save(post); + + // 빌더 패턴을 사용하여 EduContent 생성하면서 Post 엔터티를 설정 + EduContent eduContent = EduContent.builder() + .title(request.getTitle()) + .content(request.getContent()) + .post(post) // Post 엔터티를 설정 + .build(); + + // EduContent 저장 + EduContent savedContent = eduContentRepository.save(eduContent); + return savedContent; + } + +} diff --git a/src/main/java/com/finfellows/domain/educontent/domain/repository/EduContentRepository.java b/src/main/java/com/finfellows/domain/educontent/domain/repository/EduContentRepository.java index cc97b6a..a2fc8c0 100644 --- a/src/main/java/com/finfellows/domain/educontent/domain/repository/EduContentRepository.java +++ b/src/main/java/com/finfellows/domain/educontent/domain/repository/EduContentRepository.java @@ -2,7 +2,8 @@ import com.finfellows.domain.educontent.domain.EduContent; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; - +@Repository public interface EduContentRepository extends JpaRepository { } diff --git a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java new file mode 100644 index 0000000..3e1635f --- /dev/null +++ b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java @@ -0,0 +1,24 @@ +package com.finfellows.domain.educontent.presentation; + +import com.finfellows.domain.educontent.application.EduContentService; +import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/edu") +public class EduContentController { + private final EduContentService eduContentService; + + + @PostMapping("") + public ResponseEntity saveEduContent(@RequestBody EduContentResponse request){ + EduContent response = eduContentService.createEduContent(request); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + +} From 9f07b210891181f7d87f4e0c78c0d94c6f990623 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Fri, 29 Dec 2023 16:09:51 +0900 Subject: [PATCH 08/25] =?UTF-8?q?[FEAT]=20#14=20educontent=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C/=EC=83=81=EC=84=B8=EC=A1=B0=ED=9A=8C/=EC=88=98?= =?UTF-8?q?=EC=A0=95/=EC=82=AD=EC=A0=9C=20api=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/EduContentService.java | 48 +++++++++++++++++++ .../domain/educontent/domain/EduContent.java | 5 ++ .../dto/request/EduContentRequest.java | 3 ++ .../dto/response/EduContentResponse.java | 3 ++ .../presentation/EduContentController.java | 39 ++++++++++++++- 5 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index e71b7ed..fb1b754 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -2,12 +2,17 @@ import com.finfellows.domain.educontent.domain.EduContent; import com.finfellows.domain.educontent.domain.repository.EduContentRepository; +import com.finfellows.domain.educontent.dto.request.EduContentRequest; import com.finfellows.domain.educontent.dto.response.EduContentResponse; import com.finfellows.domain.post.domain.Post; import com.finfellows.domain.post.domain.repository.PostRepository; +import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import java.util.List; +import java.util.stream.Collectors; + @Service @RequiredArgsConstructor public class EduContentService { @@ -29,4 +34,47 @@ public EduContent createEduContent(EduContentResponse request) { return savedContent; } + public List getAllEduContents() { + List eduContents = eduContentRepository.findAll(); + return eduContents.stream() + .map(eduContent -> EduContentResponse.builder() + .id(eduContent.getId()) + .title(eduContent.getTitle()) + .content(eduContent.getContent()) + .build()) + .collect(Collectors.toList()); + } + + public EduContentResponse getEduContent(Long id) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + return EduContentResponse.builder() + .id(eduContent.getId()) + .title(eduContent.getTitle()) + .content(eduContent.getContent()) + .build(); + } + + public void deleteEduContent(Long id) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + eduContentRepository.delete(eduContent); + } + + public EduContentResponse updateEduContent(Long id, EduContentRequest request) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + eduContent.updateContent(request.getTitle(), request.getContent()); + + EduContent updatedContent = eduContentRepository.save(eduContent); + + return EduContentResponse.builder() + .id(updatedContent.getId()) + .title(updatedContent.getTitle()) + .content(updatedContent.getContent()) + .build(); + } } diff --git a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java index 2317b99..04ae75a 100644 --- a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java +++ b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java @@ -36,4 +36,9 @@ public EduContent(Post post, String title, String content){ this.title=title; this.content=content; } + + public void updateContent(String title, String content) { + this.title = title; + this.content = content; + } } diff --git a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java index 77ab2c4..130e9e0 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java @@ -3,11 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder @AllArgsConstructor +@NoArgsConstructor public class EduContentRequest { + private Long id; private String title; private String content; } diff --git a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java index 849f310..d711383 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java @@ -3,11 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; +import lombok.NoArgsConstructor; @Getter @Builder @AllArgsConstructor +@NoArgsConstructor public class EduContentResponse { + private Long id; private String title; private String content; } diff --git a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java index 3e1635f..ef3ffee 100644 --- a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java +++ b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java @@ -2,23 +2,60 @@ import com.finfellows.domain.educontent.application.EduContentService; import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.dto.request.EduContentRequest; import com.finfellows.domain.educontent.dto.response.EduContentResponse; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import java.util.*; + +//교육 콘텐츠 저장 @RestController @RequiredArgsConstructor -@RequestMapping("/api/edu") +@RequestMapping("/api/learn/edu") public class EduContentController { private final EduContentService eduContentService; + //저장 @PostMapping("") public ResponseEntity saveEduContent(@RequestBody EduContentResponse request){ EduContent response = eduContentService.createEduContent(request); return new ResponseEntity<>(response, HttpStatus.CREATED); } + //전체 목록 조회(title + content) + @GetMapping + public ResponseEntity> getAllEduContents() { + List responseList = eduContentService.getAllEduContents(); + return new ResponseEntity<>(responseList, HttpStatus.OK); + } + + //상세 내용 조회 + @GetMapping("/{id}") + public ResponseEntity getEduContent(@PathVariable Long id) { + EduContentResponse response = eduContentService.getEduContent(id); + return new ResponseEntity<>(response, HttpStatus.OK); + } + + //삭제 + @DeleteMapping("/{id}") + public ResponseEntity deleteEduContent(@PathVariable Long id) { + eduContentService.deleteEduContent(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + //수정 + @PatchMapping("/{id}") + public ResponseEntity updateEduContent(@PathVariable Long id, @RequestBody EduContentRequest request) { + EduContentResponse updatedContent = eduContentService.updateEduContent(id, request); + return new ResponseEntity<>(updatedContent, HttpStatus.OK); + } + + + + + } From 79ca1d6fe534c2b31eb788813a78dde3d0650708 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Tue, 2 Jan 2024 04:34:56 +0900 Subject: [PATCH 09/25] =?UTF-8?q?[FEAT]=20#15=20newscontent=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5/=EC=A1=B0=ED=9A=8C/=EC=83=81=EC=84=B8=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C/=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20api=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/NewsContentService.java | 84 +++++++++++++++++++ .../newscontent/domain/NewsContent.java | 43 ++++++++++ .../repository/NewsContentRepository.java | 9 ++ .../dto/request/NewsContentRequest.java | 16 ++++ .../dto/response/NewsContentResponse.java | 16 ++++ .../presentation/NewsContentController.java | 56 +++++++++++++ 6 files changed, 224 insertions(+) create mode 100644 src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java create mode 100644 src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java create mode 100644 src/main/java/com/finfellows/domain/newscontent/domain/repository/NewsContentRepository.java create mode 100644 src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java create mode 100644 src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java create mode 100644 src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java new file mode 100644 index 0000000..11118ed --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -0,0 +1,84 @@ +package com.finfellows.domain.newscontent.application; + +import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.dto.request.EduContentRequest; +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import com.finfellows.domain.newscontent.domain.NewsContent; +import com.finfellows.domain.newscontent.domain.repository.NewsContentRepository; +import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; +import com.finfellows.domain.newscontent.dto.response.NewsContentResponse; +import com.finfellows.domain.post.domain.Post; +import com.finfellows.domain.post.domain.repository.PostRepository; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class NewsContentService { + private final NewsContentRepository newsContentRepository; + private final PostRepository postRepository; + + public NewsContent createNewsContent(NewsContentResponse request) { + Post post = new Post(); + postRepository.save(post); + + // 빌더 패턴을 사용하여 EduContent 생성하면서 Post 엔터티를 설정 + NewsContent newsContent = NewsContent.builder() + .title(request.getTitle()) + .content(request.getContent()) + .post(post) // Post 엔터티를 설정 + .build(); + + // EduContent 저장 + NewsContent savedContent = newsContentRepository.save(newsContent); + return savedContent; + } + + public List getAllNewsContents() { + List newsContents = newsContentRepository.findAll(); + return newsContents.stream() + .map(newsContent -> NewsContentResponse.builder() + .id(newsContent.getId()) + .title(newsContent.getTitle()) + .content(newsContent.getContent()) + .build()) + .collect(Collectors.toList()); + } + + public NewsContentResponse getNewsContent(Long id) { + NewsContent newsContent = newsContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); + + return NewsContentResponse.builder() + .id(newsContent.getId()) + .title(newsContent.getTitle()) + .content(newsContent.getContent()) + .build(); + } + + public void deleteNewsContent(Long id) { + NewsContent newsContent = newsContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); + + newsContentRepository.delete(newsContent); + } + + public NewsContentResponse updateNewsContent(Long id, NewsContentRequest request) { + NewsContent newsContent = newsContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); + + newsContent.updateContent(request.getTitle(), request.getContent()); + + NewsContent updatedContent = newsContentRepository.save(newsContent); + + return NewsContentResponse.builder() + .id(updatedContent.getId()) + .title(updatedContent.getTitle()) + .content(updatedContent.getContent()) + .build(); + } +} diff --git a/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java b/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java new file mode 100644 index 0000000..5d6006c --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java @@ -0,0 +1,43 @@ +package com.finfellows.domain.newscontent.domain; + +import com.finfellows.domain.common.BaseEntity; +import com.finfellows.domain.post.domain.Post; +import jakarta.persistence.*; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Where; + +@Entity +@Table(name="NewsContent") +@NoArgsConstructor +@Getter +@Where(clause = "status = 'ACTIVE'") +public class NewsContent extends BaseEntity { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="id", updatable = false) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="post_id") + private Post post; + + @Column(name="title") + private String title; + + @Column(name="content") + private String content; + + @Builder + public NewsContent(Post post, String title, String content){ + this.post=post; + this.title=title; + this.content=content; + } + + public void updateContent(String title, String content) { + this.title = title; + this.content = content; + } +} diff --git a/src/main/java/com/finfellows/domain/newscontent/domain/repository/NewsContentRepository.java b/src/main/java/com/finfellows/domain/newscontent/domain/repository/NewsContentRepository.java new file mode 100644 index 0000000..150ccd4 --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/domain/repository/NewsContentRepository.java @@ -0,0 +1,9 @@ +package com.finfellows.domain.newscontent.domain.repository; + +import com.finfellows.domain.newscontent.domain.NewsContent; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface NewsContentRepository extends JpaRepository { +} diff --git a/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java b/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java new file mode 100644 index 0000000..40066a1 --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java @@ -0,0 +1,16 @@ +package com.finfellows.domain.newscontent.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewsContentRequest { + private Long id; + private String title; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java b/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java new file mode 100644 index 0000000..584e34c --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java @@ -0,0 +1,16 @@ +package com.finfellows.domain.newscontent.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class NewsContentResponse { + private Long id; + private String title; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java new file mode 100644 index 0000000..8453819 --- /dev/null +++ b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java @@ -0,0 +1,56 @@ +package com.finfellows.domain.newscontent.presentation; + +import com.finfellows.domain.newscontent.application.NewsContentService; +import com.finfellows.domain.newscontent.domain.NewsContent; +import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; +import com.finfellows.domain.newscontent.dto.response.NewsContentResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/learn/news") +public class NewsContentController { + private final NewsContentService newsContentService; + + //저장 + @PostMapping("") + public ResponseEntity saveNewsContent(@RequestBody NewsContentResponse request){ + NewsContent response = newsContentService.createNewsContent(request); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + //전체 목록 조회(title + content) + @GetMapping + public ResponseEntity> getAllNewsContents() { + List responseList = newsContentService.getAllNewsContents(); + return new ResponseEntity<>(responseList, HttpStatus.OK); + } + + //상세 내용 조회 + @GetMapping("/{id}") + public ResponseEntity getNewsContent(@PathVariable Long id) { + NewsContentResponse response = newsContentService.getNewsContent(id); + return new ResponseEntity<>(response, HttpStatus.OK); + } + + //삭제 + @DeleteMapping("/{id}") + public ResponseEntity deleteNewsContent(@PathVariable Long id) { + newsContentService.deleteNewsContent(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + //수정 + @PatchMapping("/{id}") + public ResponseEntity updateNewsContent(@PathVariable Long id, @RequestBody NewsContentRequest request) { + NewsContentResponse updatedContent = newsContentService.updateNewsContent(id, request); + return new ResponseEntity<>(updatedContent, HttpStatus.OK); + } + + +} From 1a733b4d46f36b03277adb9563948fbb8a5dc391 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Wed, 3 Jan 2024 12:13:33 +0900 Subject: [PATCH 10/25] =?UTF-8?q?[FEAT]=20#19=20content=20=EC=A0=80?= =?UTF-8?q?=EC=9E=A5/=EC=A1=B0=ED=9A=8C/=EC=83=81=EC=84=B8=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C/=EC=88=98=EC=A0=95/=EC=82=AD=EC=A0=9C=20api=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../post/application/ContentService.java | 83 +++++++++++++++++++ .../domain/post/domain/Content.java | 83 ++++++++++--------- .../domain/repository/ContentRepository.java | 16 ++-- .../post/dto/request/ContentRequest.java | 18 ++++ .../post/dto/response/ContentResponse.java | 18 ++++ .../post/presentation/ContentController.java | 80 ++++++++++++++++++ 6 files changed, 254 insertions(+), 44 deletions(-) create mode 100644 src/main/java/com/finfellows/domain/post/application/ContentService.java create mode 100644 src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java create mode 100644 src/main/java/com/finfellows/domain/post/dto/response/ContentResponse.java create mode 100644 src/main/java/com/finfellows/domain/post/presentation/ContentController.java diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java new file mode 100644 index 0000000..57740e1 --- /dev/null +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -0,0 +1,83 @@ +package com.finfellows.domain.post.application; + +import com.finfellows.domain.post.domain.Content; +import com.finfellows.domain.post.domain.Post; +import com.finfellows.domain.post.domain.repository.ContentRepository; +import com.finfellows.domain.post.domain.repository.PostRepository; +import com.finfellows.domain.post.dto.request.ContentRequest; +import com.finfellows.domain.post.dto.response.ContentResponse; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class ContentService { + private final ContentRepository contentRepository; + private final PostRepository postRepository; + + public Content createContent(ContentResponse request) { + Post post = new Post(); + postRepository.save(post); + + // 빌더 패턴을 사용하여 Content 생성하면서 Post 엔터티를 설정 + Content content = Content.builder() + .title(request.getTitle()) + .content(request.getContent()) + .post_id(post) // Post 엔터티를 설정 + .build(); + + // Content 저장 + Content savedContent = contentRepository.save(content); + return savedContent; + } + + public List getAllContents() { + List contents = contentRepository.findAll(); + return contents.stream() + .map(content -> ContentResponse.builder() + .id(content.getId()) + .created_at(content.getPost_id().getCreatedAt()) // 수정된 부분 + .title(content.getTitle()) + .content(content.getContent()) + .build()) + .collect(Collectors.toList()); + } + + public ContentResponse getContent(Long id) { + Content content = contentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); + + return ContentResponse.builder() + .id(content.getId()) + .created_at(content.getPost_id().getCreatedAt()) + .title(content.getTitle()) + .content(content.getContent()) + .build(); + } + + public void deleteContent(Long id) { + Content content = contentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); + + contentRepository.delete(content); + } + + public ContentResponse updateContent(Long id, ContentRequest request) { + Content content = contentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); + + content.updateContent(request.getTitle(), request.getContent()); + + Content updatedContent = contentRepository.save(content); + + return ContentResponse.builder() + .id(updatedContent.getId()) + .title(updatedContent.getTitle()) + .content(updatedContent.getContent()) + .build(); + } +} diff --git a/src/main/java/com/finfellows/domain/post/domain/Content.java b/src/main/java/com/finfellows/domain/post/domain/Content.java index c7d0dc7..d83e8b3 100644 --- a/src/main/java/com/finfellows/domain/post/domain/Content.java +++ b/src/main/java/com/finfellows/domain/post/domain/Content.java @@ -1,37 +1,46 @@ -package com.finfellows.domain.post.domain; - -import jakarta.persistence.*; -import lombok.AccessLevel; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.Where; - -@Entity -@Table(name="Content") -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Getter -@Where(clause = "status = 'ACTIVE'") -public class Content { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "id", updatable = false) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name="id") - private Post post_id; - - @Column(name="sequence", nullable = false) - private Long sequence; - - @Column(name="content") - private String content; - - @Builder - public Content(Post post_id, Long sequence, String content){ - this.post_id=post_id; - this.sequence=sequence; - this.content=content; - } -} +package com.finfellows.domain.post.domain; + +import com.finfellows.domain.common.Status; +import jakarta.persistence.*; +import lombok.AccessLevel; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Where; + +import java.time.LocalDate; + +@Entity +@Table(name="Content") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +@Where(clause = "status = 'ACTIVE'") +public class Content { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "id", updatable = false) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="post_id") + private Post post_id; + + @Column(name="title") + private String title; + + @Column(name="content") + private String content; + + + @Builder + public Content(Post post_id, String title, String content){ + this.post_id=post_id; + this.title=title; + this.content=content; + } + + public void updateContent(String title, String content) { + this.title = title; + this.content = content; + } +} diff --git a/src/main/java/com/finfellows/domain/post/domain/repository/ContentRepository.java b/src/main/java/com/finfellows/domain/post/domain/repository/ContentRepository.java index eafd9f6..859487e 100644 --- a/src/main/java/com/finfellows/domain/post/domain/repository/ContentRepository.java +++ b/src/main/java/com/finfellows/domain/post/domain/repository/ContentRepository.java @@ -1,7 +1,9 @@ -package com.finfellows.domain.post.domain.repository; - -import com.finfellows.domain.post.domain.Post; -import org.springframework.data.jpa.repository.JpaRepository; - -public interface ContentRepository extends JpaRepository { -} +package com.finfellows.domain.post.domain.repository; + +import com.finfellows.domain.post.domain.Content; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface ContentRepository extends JpaRepository { +} diff --git a/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java b/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java new file mode 100644 index 0000000..877e00b --- /dev/null +++ b/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java @@ -0,0 +1,18 @@ +package com.finfellows.domain.post.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ContentRequest { + private Long id; + private LocalDateTime created_at; + private String title; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/post/dto/response/ContentResponse.java b/src/main/java/com/finfellows/domain/post/dto/response/ContentResponse.java new file mode 100644 index 0000000..8aacfbd --- /dev/null +++ b/src/main/java/com/finfellows/domain/post/dto/response/ContentResponse.java @@ -0,0 +1,18 @@ +package com.finfellows.domain.post.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class ContentResponse { + private Long id; + private LocalDateTime created_at; + private String title; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/post/presentation/ContentController.java b/src/main/java/com/finfellows/domain/post/presentation/ContentController.java new file mode 100644 index 0000000..9ebf354 --- /dev/null +++ b/src/main/java/com/finfellows/domain/post/presentation/ContentController.java @@ -0,0 +1,80 @@ +package com.finfellows.domain.post.presentation; + +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import com.finfellows.domain.post.application.ContentService; +import com.finfellows.domain.post.dto.request.ContentRequest; +import com.finfellows.domain.post.dto.response.ContentResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/post") +@Tag(name = "Content", description = "Content API") +public class ContentController { + private final ContentService contentService; + + @Operation(summary = "공지사항 작성", description = "공지사항을 작성합니다.") + @ApiResponse(responseCode = "201", description = "공지사항을 작성 성공", content={ + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = ContentResponse.class))) + }) + @PostMapping("") + public ResponseEntity saveContent(@RequestBody ContentResponse request) { + com.finfellows.domain.post.domain.Content response = contentService.createContent(request); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + @Operation(summary = "공지사항 목록 조회", description = "공지사항 목록을 조회합니다.") + @ApiResponse(responseCode = "200", description = "공지사항 목록 조회 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = ContentResponse.class)) + }) + @GetMapping("") + public ResponseEntity> getAllContents() { + List responseList = contentService.getAllContents(); + return new ResponseEntity<>(responseList, HttpStatus.OK); + } + + + @Operation(summary = "공지사항 조회", description = "공지사항을 조회합니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "공지사항 조회 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = ContentResponse.class)) + }), + @ApiResponse(responseCode = "404", description = "공지사항을 찾을 수 없습니다.") + }) + + @GetMapping("/{id}") + public ResponseEntity getContent(@PathVariable Long id) { + ContentResponse response = contentService.getContent(id); + return new ResponseEntity<>(response, HttpStatus.OK); + } + + @Operation(summary = "공지사항 삭제", description = "공지사항을 삭제합니다.") + @ApiResponse(responseCode = "204", description = "공지사항 삭제 성공") + @DeleteMapping("/{id}") + public ResponseEntity deleteContent(@PathVariable Long id) { + contentService.deleteContent(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Operation(summary = "공지사항 수정", description = "공지사항을 수정합니다.") + @ApiResponse(responseCode = "200", description = "공지사항 수정 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = ContentResponse.class)) + }) + @PatchMapping("/{id}") + public ResponseEntity updateContent(@PathVariable Long id, @RequestBody ContentRequest request) { + ContentResponse updatedContent = contentService.updateContent(id, request); + return new ResponseEntity<>(updatedContent, HttpStatus.OK); + } +} \ No newline at end of file From 920b6940cd39d4b47ad6703ba1287416520427b3 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Wed, 3 Jan 2024 12:19:07 +0900 Subject: [PATCH 11/25] =?UTF-8?q?[FEAT]=20#19=20swagger=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/EduContentController.java | 135 ++++++++++-------- .../presentation/NewsContentController.java | 36 +++-- 2 files changed, 101 insertions(+), 70 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java index ef3ffee..c9fa017 100644 --- a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java +++ b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java @@ -1,61 +1,74 @@ -package com.finfellows.domain.educontent.presentation; - -import com.finfellows.domain.educontent.application.EduContentService; -import com.finfellows.domain.educontent.domain.EduContent; -import com.finfellows.domain.educontent.dto.request.EduContentRequest; -import com.finfellows.domain.educontent.dto.response.EduContentResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.*; - -//교육 콘텐츠 저장 -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/learn/edu") -public class EduContentController { - private final EduContentService eduContentService; - - - //저장 - @PostMapping("") - public ResponseEntity saveEduContent(@RequestBody EduContentResponse request){ - EduContent response = eduContentService.createEduContent(request); - return new ResponseEntity<>(response, HttpStatus.CREATED); - } - - //전체 목록 조회(title + content) - @GetMapping - public ResponseEntity> getAllEduContents() { - List responseList = eduContentService.getAllEduContents(); - return new ResponseEntity<>(responseList, HttpStatus.OK); - } - - //상세 내용 조회 - @GetMapping("/{id}") - public ResponseEntity getEduContent(@PathVariable Long id) { - EduContentResponse response = eduContentService.getEduContent(id); - return new ResponseEntity<>(response, HttpStatus.OK); - } - - //삭제 - @DeleteMapping("/{id}") - public ResponseEntity deleteEduContent(@PathVariable Long id) { - eduContentService.deleteEduContent(id); - return new ResponseEntity<>(HttpStatus.NO_CONTENT); - } - - //수정 - @PatchMapping("/{id}") - public ResponseEntity updateEduContent(@PathVariable Long id, @RequestBody EduContentRequest request) { - EduContentResponse updatedContent = eduContentService.updateEduContent(id, request); - return new ResponseEntity<>(updatedContent, HttpStatus.OK); - } - - - - - -} +package com.finfellows.domain.educontent.presentation; + +import com.finfellows.domain.educontent.application.EduContentService; +import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.dto.request.EduContentRequest; +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/learn/edu") +@Tag(name = "EduContent", description = "EduContent API") +public class EduContentController { + private final EduContentService eduContentService; + + @Operation(summary = "교육콘텐츠 저장", description = "교육콘텐츠를 저장합니다.") + @ApiResponse(responseCode = "201", description = "교육콘텐츠 저장 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = EduContentResponse.class))) + }) + @PostMapping("") + public ResponseEntity saveEduContent(@RequestBody EduContentResponse request) { + EduContent response = eduContentService.createEduContent(request); + return new ResponseEntity<>(response, HttpStatus.CREATED); + } + + @Operation(summary = "교육콘텐츠 전체 목록 조회", description = "교육콘텐츠 전체 목록을 조회합니다.") + @ApiResponse(responseCode = "200", description = "E교육콘텐츠 목록 조회 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = EduContentResponse.class))) + }) + @GetMapping + public ResponseEntity> getAllEduContents() { + List responseList = eduContentService.getAllEduContents(); + return new ResponseEntity<>(responseList, HttpStatus.OK); + } + + @Operation(summary = "교육콘텐츠 상세 내용 조회", description = "교육콘텐츠 상세 내용을 조회합니다.") + @ApiResponse(responseCode = "200", description = "교육콘텐츠 조회 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = EduContentResponse.class)) + }) + @GetMapping("/{id}") + public ResponseEntity getEduContent(@PathVariable Long id) { + EduContentResponse response = eduContentService.getEduContent(id); + return new ResponseEntity<>(response, HttpStatus.OK); + } + + @Operation(summary = "교육콘텐츠 삭제", description = "교육콘텐츠를 삭제합니다.") + @ApiResponse(responseCode = "204", description = "교육콘텐츠 삭제 성공") + @DeleteMapping("/{id}") + public ResponseEntity deleteEduContent(@PathVariable Long id) { + eduContentService.deleteEduContent(id); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @Operation(summary = "교육콘텐츠 수정", description = "교육콘텐츠를 수정합니다.") + @ApiResponse(responseCode = "200", description = "교육콘텐츠 수정 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = EduContentResponse.class)) + }) + @PatchMapping("/{id}") + public ResponseEntity updateEduContent(@PathVariable Long id, @RequestBody EduContentRequest request) { + EduContentResponse updatedContent = eduContentService.updateEduContent(id, request); + return new ResponseEntity<>(updatedContent, HttpStatus.OK); + } +} \ No newline at end of file diff --git a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java index 8453819..db28bc3 100644 --- a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java +++ b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java @@ -4,6 +4,12 @@ import com.finfellows.domain.newscontent.domain.NewsContent; import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; import com.finfellows.domain.newscontent.dto.response.NewsContentResponse; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -14,43 +20,55 @@ @RestController @RequiredArgsConstructor @RequestMapping("/api/learn/news") +@Tag(name = "NewsContent", description = "NewsContent API") public class NewsContentController { private final NewsContentService newsContentService; - //저장 + @Operation(summary = "뉴스콘텐츠 저장", description = "뉴스콘텐츠를 저장합니다.") + @ApiResponse(responseCode = "201", description = "뉴스콘텐츠 저장 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = NewsContentResponse.class))) + }) @PostMapping("") - public ResponseEntity saveNewsContent(@RequestBody NewsContentResponse request){ + public ResponseEntity saveNewsContent(@RequestBody NewsContentResponse request) { NewsContent response = newsContentService.createNewsContent(request); return new ResponseEntity<>(response, HttpStatus.CREATED); } - //전체 목록 조회(title + content) + @Operation(summary = "뉴스콘텐츠 전체 목록 조회", description = "뉴스콘텐츠 전체 목록을 조회합니다.") + @ApiResponse(responseCode = "200", description = "뉴스콘텐츠 목록 조회 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = NewsContentResponse.class))) + }) @GetMapping public ResponseEntity> getAllNewsContents() { List responseList = newsContentService.getAllNewsContents(); return new ResponseEntity<>(responseList, HttpStatus.OK); } - //상세 내용 조회 + @Operation(summary = "뉴스콘텐츠 상세 내용 조회", description = "뉴스콘텐츠 상세 내용을 조회합니다.") + @ApiResponse(responseCode = "200", description = "뉴스콘텐츠 조회 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = NewsContentResponse.class)) + }) @GetMapping("/{id}") public ResponseEntity getNewsContent(@PathVariable Long id) { NewsContentResponse response = newsContentService.getNewsContent(id); return new ResponseEntity<>(response, HttpStatus.OK); } - //삭제 + @Operation(summary = "뉴스콘텐츠 삭제", description = "뉴스콘텐츠를 삭제합니다.") + @ApiResponse(responseCode = "204", description = "뉴스콘텐츠 삭제 성공") @DeleteMapping("/{id}") public ResponseEntity deleteNewsContent(@PathVariable Long id) { newsContentService.deleteNewsContent(id); return new ResponseEntity<>(HttpStatus.NO_CONTENT); } - //수정 + @Operation(summary = "뉴스콘텐츠 수정", description = "뉴스콘텐츠를 수정합니다.") + @ApiResponse(responseCode = "200", description = "뉴스콘텐츠 수정 성공", content = { + @Content(mediaType = "application/json", schema = @Schema(implementation = NewsContentResponse.class)) + }) @PatchMapping("/{id}") public ResponseEntity updateNewsContent(@PathVariable Long id, @RequestBody NewsContentRequest request) { NewsContentResponse updatedContent = newsContentService.updateNewsContent(id, request); return new ResponseEntity<>(updatedContent, HttpStatus.OK); } - - -} +} \ No newline at end of file From b8dda6bd84e31841e39dc3efdedb80e0a05f21c2 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Wed, 3 Jan 2024 19:16:51 +0900 Subject: [PATCH 12/25] =?UTF-8?q?[FEAT]=20#19=20readOnly=EB=A5=BC=20?= =?UTF-8?q?=EC=9C=84=ED=95=9C=20Transactional=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/EduContentService.java | 167 +++++++++--------- .../application/NewsContentService.java | 13 +- .../post/application/ContentService.java | 6 + 3 files changed, 101 insertions(+), 85 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index fb1b754..1705976 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -1,80 +1,87 @@ -package com.finfellows.domain.educontent.application; - -import com.finfellows.domain.educontent.domain.EduContent; -import com.finfellows.domain.educontent.domain.repository.EduContentRepository; -import com.finfellows.domain.educontent.dto.request.EduContentRequest; -import com.finfellows.domain.educontent.dto.response.EduContentResponse; -import com.finfellows.domain.post.domain.Post; -import com.finfellows.domain.post.domain.repository.PostRepository; -import jakarta.persistence.EntityNotFoundException; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -import java.util.List; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class EduContentService { - private final EduContentRepository eduContentRepository; - private final PostRepository postRepository; - public EduContent createEduContent(EduContentResponse request) { - Post post = new Post(); - postRepository.save(post); - - // 빌더 패턴을 사용하여 EduContent 생성하면서 Post 엔터티를 설정 - EduContent eduContent = EduContent.builder() - .title(request.getTitle()) - .content(request.getContent()) - .post(post) // Post 엔터티를 설정 - .build(); - - // EduContent 저장 - EduContent savedContent = eduContentRepository.save(eduContent); - return savedContent; - } - - public List getAllEduContents() { - List eduContents = eduContentRepository.findAll(); - return eduContents.stream() - .map(eduContent -> EduContentResponse.builder() - .id(eduContent.getId()) - .title(eduContent.getTitle()) - .content(eduContent.getContent()) - .build()) - .collect(Collectors.toList()); - } - - public EduContentResponse getEduContent(Long id) { - EduContent eduContent = eduContentRepository.findById(id) - .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); - - return EduContentResponse.builder() - .id(eduContent.getId()) - .title(eduContent.getTitle()) - .content(eduContent.getContent()) - .build(); - } - - public void deleteEduContent(Long id) { - EduContent eduContent = eduContentRepository.findById(id) - .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); - - eduContentRepository.delete(eduContent); - } - - public EduContentResponse updateEduContent(Long id, EduContentRequest request) { - EduContent eduContent = eduContentRepository.findById(id) - .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); - - eduContent.updateContent(request.getTitle(), request.getContent()); - - EduContent updatedContent = eduContentRepository.save(eduContent); - - return EduContentResponse.builder() - .id(updatedContent.getId()) - .title(updatedContent.getTitle()) - .content(updatedContent.getContent()) - .build(); - } -} +package com.finfellows.domain.educontent.application; + +import com.finfellows.domain.educontent.domain.EduContent; +import com.finfellows.domain.educontent.domain.repository.EduContentRepository; +import com.finfellows.domain.educontent.dto.request.EduContentRequest; +import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import com.finfellows.domain.post.domain.Post; +import com.finfellows.domain.post.domain.repository.PostRepository; +import jakarta.persistence.EntityNotFoundException; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class EduContentService { + private final EduContentRepository eduContentRepository; + private final PostRepository postRepository; + + @Transactional + public EduContent createEduContent(EduContentResponse request) { + Post post = new Post(); + postRepository.save(post); + + // 빌더 패턴을 사용하여 EduContent 생성하면서 Post 엔터티를 설정 + EduContent eduContent = EduContent.builder() + .title(request.getTitle()) + .content(request.getContent()) + .post(post) // Post 엔터티를 설정 + .build(); + + // EduContent 저장 + EduContent savedContent = eduContentRepository.save(eduContent); + return savedContent; + } + + @Transactional(readOnly = true) + public List getAllEduContents() { + List eduContents = eduContentRepository.findAll(); + return eduContents.stream() + .map(eduContent -> EduContentResponse.builder() + .id(eduContent.getId()) + .title(eduContent.getTitle()) + .content(eduContent.getContent()) + .build()) + .collect(Collectors.toList()); + } + + @Transactional(readOnly = true) + public EduContentResponse getEduContent(Long id) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + return EduContentResponse.builder() + .id(eduContent.getId()) + .title(eduContent.getTitle()) + .content(eduContent.getContent()) + .build(); + } + + @Transactional + public void deleteEduContent(Long id) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + eduContentRepository.delete(eduContent); + } + + @Transactional + public EduContentResponse updateEduContent(Long id, EduContentRequest request) { + EduContent eduContent = eduContentRepository.findById(id) + .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); + + eduContent.updateContent(request.getTitle(), request.getContent()); + + EduContent updatedContent = eduContentRepository.save(eduContent); + + return EduContentResponse.builder() + .id(updatedContent.getId()) + .title(updatedContent.getTitle()) + .content(updatedContent.getContent()) + .build(); + } +} diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index 11118ed..9cc0af5 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -1,8 +1,5 @@ package com.finfellows.domain.newscontent.application; -import com.finfellows.domain.educontent.domain.EduContent; -import com.finfellows.domain.educontent.dto.request.EduContentRequest; -import com.finfellows.domain.educontent.dto.response.EduContentResponse; import com.finfellows.domain.newscontent.domain.NewsContent; import com.finfellows.domain.newscontent.domain.repository.NewsContentRepository; import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; @@ -12,6 +9,7 @@ import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.List; import java.util.stream.Collectors; @@ -22,22 +20,24 @@ public class NewsContentService { private final NewsContentRepository newsContentRepository; private final PostRepository postRepository; + @Transactional public NewsContent createNewsContent(NewsContentResponse request) { Post post = new Post(); postRepository.save(post); - // 빌더 패턴을 사용하여 EduContent 생성하면서 Post 엔터티를 설정 + // 빌더 패턴을 사용하여 NewsContent 생성하면서 Post 엔터티를 설정 NewsContent newsContent = NewsContent.builder() .title(request.getTitle()) .content(request.getContent()) .post(post) // Post 엔터티를 설정 .build(); - // EduContent 저장 + // NewsContent 저장 NewsContent savedContent = newsContentRepository.save(newsContent); return savedContent; } + @Transactional(readOnly = true) public List getAllNewsContents() { List newsContents = newsContentRepository.findAll(); return newsContents.stream() @@ -49,6 +49,7 @@ public List getAllNewsContents() { .collect(Collectors.toList()); } + @Transactional(readOnly = true) public NewsContentResponse getNewsContent(Long id) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); @@ -60,6 +61,7 @@ public NewsContentResponse getNewsContent(Long id) { .build(); } + @Transactional public void deleteNewsContent(Long id) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); @@ -67,6 +69,7 @@ public void deleteNewsContent(Long id) { newsContentRepository.delete(newsContent); } + @Transactional public NewsContentResponse updateNewsContent(Long id, NewsContentRequest request) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java index 57740e1..7b396f2 100644 --- a/src/main/java/com/finfellows/domain/post/application/ContentService.java +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -9,6 +9,7 @@ import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.*; import java.util.stream.Collectors; @@ -19,6 +20,7 @@ public class ContentService { private final ContentRepository contentRepository; private final PostRepository postRepository; + @Transactional public Content createContent(ContentResponse request) { Post post = new Post(); postRepository.save(post); @@ -35,6 +37,7 @@ public Content createContent(ContentResponse request) { return savedContent; } + @Transactional(readOnly = true) public List getAllContents() { List contents = contentRepository.findAll(); return contents.stream() @@ -47,6 +50,7 @@ public List getAllContents() { .collect(Collectors.toList()); } + @Transactional(readOnly = true) public ContentResponse getContent(Long id) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); @@ -59,6 +63,7 @@ public ContentResponse getContent(Long id) { .build(); } + @Transactional public void deleteContent(Long id) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); @@ -66,6 +71,7 @@ public void deleteContent(Long id) { contentRepository.delete(content); } + @Transactional public ContentResponse updateContent(Long id, ContentRequest request) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); From 8e5b3a0c369976d00daad955538fe42dfd00323b Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Wed, 3 Jan 2024 20:47:20 +0900 Subject: [PATCH 13/25] =?UTF-8?q?[FEAT]=20#39=20chatbot,=20comment=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/chatbot/domain/Chatbot.java | 5 ++ .../domain/repository/ChatbotRepository.java | 4 + .../chatgpt/application/ChatGptService.java | 81 ++++++++---------- .../domain/chatgpt/domain/ChatGptMessage.java | 11 +++ .../dto/request/ChatgptQuestionRequest.java | 12 +++ .../dto/{ => request}/ChatgptRequest.java | 2 +- .../chatgpt/dto/response/ChatgptResponse.java | 21 +++++ .../presentation/ChatGptController.java | 7 -- .../comment/application/CommentService.java | 84 +++++++++++++++++++ .../domain/comment/domain/Comment.java | 33 ++++++++ .../domain/repository/CommentRepository.java | 7 ++ .../presentation/CommentController.java | 9 ++ 12 files changed, 221 insertions(+), 55 deletions(-) create mode 100644 src/main/java/com/finfellows/domain/chatbot/domain/Chatbot.java create mode 100644 src/main/java/com/finfellows/domain/chatbot/domain/repository/ChatbotRepository.java create mode 100644 src/main/java/com/finfellows/domain/chatgpt/domain/ChatGptMessage.java create mode 100644 src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptQuestionRequest.java rename src/main/java/com/finfellows/domain/chatgpt/dto/{ => request}/ChatgptRequest.java (95%) create mode 100644 src/main/java/com/finfellows/domain/chatgpt/dto/response/ChatgptResponse.java create mode 100644 src/main/java/com/finfellows/domain/comment/application/CommentService.java create mode 100644 src/main/java/com/finfellows/domain/comment/domain/Comment.java create mode 100644 src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java create mode 100644 src/main/java/com/finfellows/domain/comment/presentation/CommentController.java diff --git a/src/main/java/com/finfellows/domain/chatbot/domain/Chatbot.java b/src/main/java/com/finfellows/domain/chatbot/domain/Chatbot.java new file mode 100644 index 0000000..a2055a7 --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatbot/domain/Chatbot.java @@ -0,0 +1,5 @@ +package com.finfellows.domain.chatbot.domain; + +public class Chatbot { + +} diff --git a/src/main/java/com/finfellows/domain/chatbot/domain/repository/ChatbotRepository.java b/src/main/java/com/finfellows/domain/chatbot/domain/repository/ChatbotRepository.java new file mode 100644 index 0000000..cbce09a --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatbot/domain/repository/ChatbotRepository.java @@ -0,0 +1,4 @@ +package com.finfellows.domain.chatbot.domain.repository; + +public interface ChatbotRepository { +} diff --git a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java index f5d1caa..d81ec9d 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java +++ b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java @@ -1,22 +1,9 @@ package com.finfellows.domain.chatgpt.application; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.fasterxml.jackson.databind.PropertyNamingStrategies; -import com.finfellows.domain.chatgpt.config.ChatgptConfig; -import com.finfellows.domain.chatgpt.domain.ChatGptMessage; -import com.finfellows.domain.chatgpt.dto.ChatgptQuestionRequest; -import com.finfellows.domain.chatgpt.dto.ChatgptRequest; import io.github.flashvayne.chatgpt.service.ChatgptService; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Value; -import org.springframework.http.HttpHeaders; -import org.springframework.http.MediaType; import org.springframework.stereotype.Service; -import org.springframework.web.reactive.function.client.WebClient; -import reactor.core.publisher.Flux; -import java.util.*; @Service @RequiredArgsConstructor @@ -27,40 +14,40 @@ public class ChatGptService { @Value("${GPT_Token}") private String apiKey; - private final ObjectMapper objectMapper = new ObjectMapper() - .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) - .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE ); - public Flux ask(ChatgptQuestionRequest chatGptQuestionRequest) throws JsonProcessingException { - WebClient client = WebClient.builder() - .baseUrl(ChatgptConfig.CHAT_URL) - .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) - .defaultHeader(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey) - .build(); - - List messages = new ArrayList<>(); - messages.add(ChatGptMessage.builder() - .role(ChatgptConfig.ROLE) - .content(chatGptQuestionRequest.getQuestion()) - .build()); - - ChatgptRequest chatGptRequest = new ChatgptRequest( - ChatgptConfig.CHAT_MODEL, - ChatgptConfig.MAX_TOKEN, - ChatgptConfig.TEMPERATURE, - ChatgptConfig.STREAM_TRUE, - messages - ); - - String requestValue = objectMapper.writeValueAsString(chatGptRequest); - - Flux eventStream = client.post() - .bodyValue(requestValue) - .accept(MediaType.TEXT_EVENT_STREAM) - .retrieve() - .bodyToFlux(String.class); - - return eventStream; - } +// private final ObjectMapper objectMapper = new ObjectMapper() +// .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) +// .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE ); +// public Flux ask(ChatgptQuestionRequest chatGptQuestionRequest) throws JsonProcessingException { +// WebClient client = WebClient.builder() +// .baseUrl(ChatgptConfig.CHAT_URL) +// .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) +// .defaultHeader(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey) +// .build(); +// +// List messages = new ArrayList<>(); +// messages.add(ChatGptMessage.builder() +// .role(ChatgptConfig.ROLE) +// .content(chatGptQuestionRequest.getQuestion()) +// .build()); +// +// ChatgptRequest chatGptRequest = new ChatgptRequest( +// ChatgptConfig.CHAT_MODEL, +// ChatgptConfig.MAX_TOKEN, +// ChatgptConfig.TEMPERATURE, +// ChatgptConfig.STREAM_TRUE, +// messages +// ); +// +// String requestValue = objectMapper.writeValueAsString(chatGptRequest); +// +// Flux eventStream = client.post() +// .bodyValue(requestValue) +// .accept(MediaType.TEXT_EVENT_STREAM) +// .retrieve() +// .bodyToFlux(String.class); +// +// return eventStream; +// } // 단답 답변 public String getChatResponse(String prompt) { diff --git a/src/main/java/com/finfellows/domain/chatgpt/domain/ChatGptMessage.java b/src/main/java/com/finfellows/domain/chatgpt/domain/ChatGptMessage.java new file mode 100644 index 0000000..3fb0533 --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/domain/ChatGptMessage.java @@ -0,0 +1,11 @@ +package com.finfellows.domain.chatgpt.domain; + +import lombok.Builder; +import lombok.Data; + +@Builder +@Data +public class ChatGptMessage { + private String role; + private String content; +} diff --git a/src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptQuestionRequest.java b/src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptQuestionRequest.java new file mode 100644 index 0000000..d96795e --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptQuestionRequest.java @@ -0,0 +1,12 @@ +package com.finfellows.domain.chatgpt.dto.request; + +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Getter +@NoArgsConstructor +public class ChatgptQuestionRequest implements Serializable { + private String question; +} diff --git a/src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java b/src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptRequest.java similarity index 95% rename from src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java rename to src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptRequest.java index 6bb229e..6f526eb 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/dto/ChatgptRequest.java +++ b/src/main/java/com/finfellows/domain/chatgpt/dto/request/ChatgptRequest.java @@ -1,4 +1,4 @@ -package com.finfellows.domain.chatgpt.dto; +package com.finfellows.domain.chatgpt.dto.request; import com.fasterxml.jackson.annotation.JsonProperty; import com.finfellows.domain.chatgpt.domain.ChatGptMessage; diff --git a/src/main/java/com/finfellows/domain/chatgpt/dto/response/ChatgptResponse.java b/src/main/java/com/finfellows/domain/chatgpt/dto/response/ChatgptResponse.java new file mode 100644 index 0000000..dcab9bc --- /dev/null +++ b/src/main/java/com/finfellows/domain/chatgpt/dto/response/ChatgptResponse.java @@ -0,0 +1,21 @@ +package com.finfellows.domain.chatgpt.dto.response; + +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import java.util.*; + +@Getter +@NoArgsConstructor +//GPT 답변에 대한 DTO +public class ChatgptResponse { + private String id; + private String model; + private List choices; + + @Getter + @Setter + public static class Usage { + private int totalTokens; + } +} diff --git a/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java index ba8343e..b10657b 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java +++ b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java @@ -1,19 +1,12 @@ package com.finfellows.domain.chatgpt.presentation; -import com.fasterxml.jackson.core.JsonProcessingException; import com.finfellows.domain.chatgpt.application.ChatGptService; -import com.finfellows.domain.chatgpt.dto.ChatgptQuestionRequest; -import jakarta.servlet.http.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.MediaType; 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 reactor.core.publisher.Flux; - -import java.util.*; @RestController @RequestMapping("/api/v1/chat-gpt") diff --git a/src/main/java/com/finfellows/domain/comment/application/CommentService.java b/src/main/java/com/finfellows/domain/comment/application/CommentService.java new file mode 100644 index 0000000..cf9a89a --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/application/CommentService.java @@ -0,0 +1,84 @@ +package com.finfellows.domain.comment.application; + +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.finfellows.domain.chatgpt.domain.ChatGptMessage; +import com.finfellows.domain.chatgpt.application.ChatGptService; +import com.finfellows.domain.chatgpt.config.ChatgptConfig; +import com.finfellows.domain.chatgpt.dto.request.ChatgptQuestionRequest; +import com.finfellows.domain.chatgpt.dto.request.ChatgptRequest; +import com.finfellows.domain.chatgpt.dto.response.ChatgptResponse; +import com.finfellows.domain.comment.domain.repository.CommentRepository; +import com.finfellows.domain.user.domain.repository.UserRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.*; +import org.springframework.http.client.SimpleClientHttpRequestFactory; +import org.springframework.stereotype.Service; +import org.springframework.web.client.RestTemplate; + +import java.util.*; + +@Service +@RequiredArgsConstructor +public class CommentService { + private final UserRepository userRepository; + private final ChatGptService chatGptService; + private final CommentRepository commentRepository; + + @Autowired + private RestTemplate restTemplate; + + @Value("${GPT_Token}") + private String apiKey; + private final ObjectMapper objectMapper = new ObjectMapper() + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + + // gpt 단답 + public HttpEntity buildHttpEntity(ChatgptRequest chatGptRequest) { + HttpHeaders httpHeaders = new HttpHeaders(); + httpHeaders.setContentType(MediaType.parseMediaType(ChatgptConfig.MEDIA_TYPE)); + httpHeaders.add(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey); + return new HttpEntity<>(chatGptRequest, httpHeaders); + } + + // gpt 단답 + public ChatgptResponse getResponse(HttpEntity chatGptRequestHttpEntity) { + + SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); + requestFactory.setConnectTimeout(60000); + //답변이 길어질 경우 TimeOut Error가 발생하니 1분정도 설정해줍니다. + requestFactory.setReadTimeout(60 * 1000); // 1min = 60 sec * 1,000ms + restTemplate.setRequestFactory(requestFactory); + + ResponseEntity responseEntity = restTemplate.postForEntity( + ChatgptConfig.CHAT_URL, + chatGptRequestHttpEntity, + ChatgptResponse.class); + + return responseEntity.getBody(); + } + + // gpt 단답 + public ChatgptResponse askQuestion(ChatgptQuestionRequest questionRequest) { + List messages = new ArrayList<>(); + messages.add(ChatGptMessage.builder() + .role(ChatgptConfig.ROLE) + .content(questionRequest.getQuestion()) + .build()); + return this.getResponse( + this.buildHttpEntity( + new ChatgptRequest( + ChatgptConfig.CHAT_MODEL, + ChatgptConfig.MAX_TOKEN, + ChatgptConfig.TEMPERATURE, + ChatgptConfig.STREAM_FALSE, + messages + ) + ) + ); + } +} diff --git a/src/main/java/com/finfellows/domain/comment/domain/Comment.java b/src/main/java/com/finfellows/domain/comment/domain/Comment.java new file mode 100644 index 0000000..00c31c2 --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/domain/Comment.java @@ -0,0 +1,33 @@ +package com.finfellows.domain.comment.domain; + +import com.finfellows.domain.common.BaseEntity; +import com.finfellows.domain.user.domain.User; +import jakarta.persistence.*; +import lombok.*; + +@Entity +@Table(name="Comment") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Getter +public class Comment extends BaseEntity { + + //질문 내용 저장 칼럼 필요함. + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name="comment_id", updatable = false, nullable = false, unique = true) + private Long commentId; + + @Column(name="comment_content") + private String commentContent; + + @ManyToOne + @JoinColumn(name="user_id") + private User userId; + + @Builder + public Comment(Long commentId, String commentContent, User userId){ + this.commentId=commentId; + this.commentContent=commentContent; + this.userId=userId; + } +} diff --git a/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java b/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java new file mode 100644 index 0000000..ec86eae --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java @@ -0,0 +1,7 @@ +package com.finfellows.domain.comment.domain.repository; + +import com.finfellows.domain.comment.domain.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentRepository extends JpaRepository { +} diff --git a/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java new file mode 100644 index 0000000..4bcc573 --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java @@ -0,0 +1,9 @@ +package com.finfellows.domain.comment.presentation; + +import lombok.RequiredArgsConstructor; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +public class CommentController { +} From 05788aed20fef0594f8a78f90e66e53fe3e07b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=B0=95=EC=84=B8=EC=A7=84?= Date: Wed, 3 Jan 2024 21:13:12 +0900 Subject: [PATCH 14/25] =?UTF-8?q?fix:=20chat=20gpt=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finfellows/domain/chatgpt/application/ChatGptService.java | 2 +- .../com/finfellows/domain/chatgpt/config/ChatgptConfig.java | 2 +- .../finfellows/domain/comment/application/CommentService.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java index d81ec9d..8704c09 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java +++ b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java @@ -12,7 +12,7 @@ public class ChatGptService { // 라이브러리 제공 private final ChatgptService chatgptService; - @Value("${GPT_Token}") + @Value("${chatgpt.api-key}") private String apiKey; // private final ObjectMapper objectMapper = new ObjectMapper() // .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) diff --git a/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java b/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java index f795a60..ae35553 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java +++ b/src/main/java/com/finfellows/domain/chatgpt/config/ChatgptConfig.java @@ -23,7 +23,7 @@ public class ChatgptConfig { public static final String MEDIA_TYPE = "application/json; charset=UTF-8"; public static final String CHAT_URL = "https://api.openai.com/v1/chat/completions"; - @Value("${GPT_Token}") + @Value("${chatgpt.api-key}") private String token; @Bean diff --git a/src/main/java/com/finfellows/domain/comment/application/CommentService.java b/src/main/java/com/finfellows/domain/comment/application/CommentService.java index cf9a89a..da5d479 100644 --- a/src/main/java/com/finfellows/domain/comment/application/CommentService.java +++ b/src/main/java/com/finfellows/domain/comment/application/CommentService.java @@ -31,7 +31,7 @@ public class CommentService { @Autowired private RestTemplate restTemplate; - @Value("${GPT_Token}") + @Value("${chatgpt.api-key}") private String apiKey; private final ObjectMapper objectMapper = new ObjectMapper() .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) From 5b4a26d878abe813f27d29e8028a9dd36d6c986b Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 4 Jan 2024 01:16:16 +0900 Subject: [PATCH 15/25] =?UTF-8?q?[FIX]=20#19=20Transactional=20annotation?= =?UTF-8?q?=20readOnly=20default=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/educontent/application/EduContentService.java | 4 ++-- .../domain/newscontent/application/NewsContentService.java | 4 ++-- .../finfellows/domain/post/application/ContentService.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index 1705976..e500e64 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class EduContentService { private final EduContentRepository eduContentRepository; private final PostRepository postRepository; @@ -37,7 +38,6 @@ public EduContent createEduContent(EduContentResponse request) { return savedContent; } - @Transactional(readOnly = true) public List getAllEduContents() { List eduContents = eduContentRepository.findAll(); return eduContents.stream() @@ -49,7 +49,7 @@ public List getAllEduContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) + public EduContentResponse getEduContent(Long id) { EduContent eduContent = eduContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index 9cc0af5..e40844f 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class NewsContentService { private final NewsContentRepository newsContentRepository; private final PostRepository postRepository; @@ -37,7 +38,6 @@ public NewsContent createNewsContent(NewsContentResponse request) { return savedContent; } - @Transactional(readOnly = true) public List getAllNewsContents() { List newsContents = newsContentRepository.findAll(); return newsContents.stream() @@ -49,7 +49,7 @@ public List getAllNewsContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) + public NewsContentResponse getNewsContent(Long id) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java index 7b396f2..bdb6a28 100644 --- a/src/main/java/com/finfellows/domain/post/application/ContentService.java +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class ContentService { private final ContentRepository contentRepository; private final PostRepository postRepository; @@ -37,7 +38,7 @@ public Content createContent(ContentResponse request) { return savedContent; } - @Transactional(readOnly = true) + public List getAllContents() { List contents = contentRepository.findAll(); return contents.stream() @@ -50,7 +51,6 @@ public List getAllContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) public ContentResponse getContent(Long id) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); From d595896fb776ca19d3ea2a3a62154807d6d93559 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 4 Jan 2024 01:17:15 +0900 Subject: [PATCH 16/25] =?UTF-8?q?Revert=20"[FIX]=20#19=20Transactional=20a?= =?UTF-8?q?nnotation=20readOnly=20default=20=EC=88=98=EC=A0=95"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit 4a18b0ebce60ff41bdacac044fd6c365adf49ca4. --- .../domain/educontent/application/EduContentService.java | 4 ++-- .../domain/newscontent/application/NewsContentService.java | 4 ++-- .../finfellows/domain/post/application/ContentService.java | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index e500e64..1705976 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -16,7 +16,6 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class EduContentService { private final EduContentRepository eduContentRepository; private final PostRepository postRepository; @@ -38,6 +37,7 @@ public EduContent createEduContent(EduContentResponse request) { return savedContent; } + @Transactional(readOnly = true) public List getAllEduContents() { List eduContents = eduContentRepository.findAll(); return eduContents.stream() @@ -49,7 +49,7 @@ public List getAllEduContents() { .collect(Collectors.toList()); } - + @Transactional(readOnly = true) public EduContentResponse getEduContent(Long id) { EduContent eduContent = eduContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index e40844f..9cc0af5 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -16,7 +16,6 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class NewsContentService { private final NewsContentRepository newsContentRepository; private final PostRepository postRepository; @@ -38,6 +37,7 @@ public NewsContent createNewsContent(NewsContentResponse request) { return savedContent; } + @Transactional(readOnly = true) public List getAllNewsContents() { List newsContents = newsContentRepository.findAll(); return newsContents.stream() @@ -49,7 +49,7 @@ public List getAllNewsContents() { .collect(Collectors.toList()); } - + @Transactional(readOnly = true) public NewsContentResponse getNewsContent(Long id) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java index bdb6a28..7b396f2 100644 --- a/src/main/java/com/finfellows/domain/post/application/ContentService.java +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -16,7 +16,6 @@ @Service @RequiredArgsConstructor -@Transactional(readOnly = true) public class ContentService { private final ContentRepository contentRepository; private final PostRepository postRepository; @@ -38,7 +37,7 @@ public Content createContent(ContentResponse request) { return savedContent; } - + @Transactional(readOnly = true) public List getAllContents() { List contents = contentRepository.findAll(); return contents.stream() @@ -51,6 +50,7 @@ public List getAllContents() { .collect(Collectors.toList()); } + @Transactional(readOnly = true) public ContentResponse getContent(Long id) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); From 6263479bccc70a3c5546c19e4d8212aeccbb7ae9 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Thu, 4 Jan 2024 01:20:18 +0900 Subject: [PATCH 17/25] =?UTF-8?q?[FIX]=20#19=20Transactional=20annotation?= =?UTF-8?q?=20readOnly=20default=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/educontent/application/EduContentService.java | 3 +-- .../domain/newscontent/application/NewsContentService.java | 3 +-- .../com/finfellows/domain/post/application/ContentService.java | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index 1705976..437605e 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class EduContentService { private final EduContentRepository eduContentRepository; private final PostRepository postRepository; @@ -37,7 +38,6 @@ public EduContent createEduContent(EduContentResponse request) { return savedContent; } - @Transactional(readOnly = true) public List getAllEduContents() { List eduContents = eduContentRepository.findAll(); return eduContents.stream() @@ -49,7 +49,6 @@ public List getAllEduContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) public EduContentResponse getEduContent(Long id) { EduContent eduContent = eduContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("EduContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index 9cc0af5..c6e0891 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class NewsContentService { private final NewsContentRepository newsContentRepository; private final PostRepository postRepository; @@ -37,7 +38,6 @@ public NewsContent createNewsContent(NewsContentResponse request) { return savedContent; } - @Transactional(readOnly = true) public List getAllNewsContents() { List newsContents = newsContentRepository.findAll(); return newsContents.stream() @@ -49,7 +49,6 @@ public List getAllNewsContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) public NewsContentResponse getNewsContent(Long id) { NewsContent newsContent = newsContentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("NewsContent not found with id: " + id)); diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java index 7b396f2..b73ef7a 100644 --- a/src/main/java/com/finfellows/domain/post/application/ContentService.java +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -16,6 +16,7 @@ @Service @RequiredArgsConstructor +@Transactional(readOnly = true) public class ContentService { private final ContentRepository contentRepository; private final PostRepository postRepository; @@ -37,7 +38,6 @@ public Content createContent(ContentResponse request) { return savedContent; } - @Transactional(readOnly = true) public List getAllContents() { List contents = contentRepository.findAll(); return contents.stream() @@ -50,7 +50,6 @@ public List getAllContents() { .collect(Collectors.toList()); } - @Transactional(readOnly = true) public ContentResponse getContent(Long id) { Content content = contentRepository.findById(id) .orElseThrow(() -> new EntityNotFoundException("Content not found with id: " + id)); From 1a4c2f986d2bfca2b2fddbc6f1153085ab068e8c Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 03:39:10 +0900 Subject: [PATCH 18/25] =?UTF-8?q?[FEAT]=20#39=20=EC=B1=97=EB=B4=87=20?= =?UTF-8?q?=EC=A7=88=EC=9D=98=EC=9D=91=EB=8B=B5=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EA=B0=9C=EB=B0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 인사말 추가, 질의응답, 조회 기능 --- .../chatgpt/application/ChatGptService.java | 52 +++++---------- .../presentation/ChatGptController.java | 29 +++++---- .../comment/application/CommentService.java | 65 ++++++++++++++++++- .../domain/comment/domain/Comment.java | 22 ++++--- .../domain/repository/CommentRepository.java | 5 ++ .../comment/dto/request/CommentRequest.java | 22 +++++++ .../comment/dto/response/CommentResponse.java | 22 +++++++ .../presentation/CommentController.java | 39 ++++++++++- .../config/security/SecurityConfig.java | 3 + 9 files changed, 198 insertions(+), 61 deletions(-) create mode 100644 src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java create mode 100644 src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java diff --git a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java index 8704c09..da6ba38 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java +++ b/src/main/java/com/finfellows/domain/chatgpt/application/ChatGptService.java @@ -14,46 +14,24 @@ public class ChatGptService { @Value("${chatgpt.api-key}") private String apiKey; -// private final ObjectMapper objectMapper = new ObjectMapper() -// .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) -// .setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE ); -// public Flux ask(ChatgptQuestionRequest chatGptQuestionRequest) throws JsonProcessingException { -// WebClient client = WebClient.builder() -// .baseUrl(ChatgptConfig.CHAT_URL) -// .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) -// .defaultHeader(ChatgptConfig.AUTHORIZATION, ChatgptConfig.BEARER + apiKey) -// .build(); -// -// List messages = new ArrayList<>(); -// messages.add(ChatGptMessage.builder() -// .role(ChatgptConfig.ROLE) -// .content(chatGptQuestionRequest.getQuestion()) -// .build()); -// -// ChatgptRequest chatGptRequest = new ChatgptRequest( -// ChatgptConfig.CHAT_MODEL, -// ChatgptConfig.MAX_TOKEN, -// ChatgptConfig.TEMPERATURE, -// ChatgptConfig.STREAM_TRUE, -// messages -// ); -// -// String requestValue = objectMapper.writeValueAsString(chatGptRequest); -// -// Flux eventStream = client.post() -// .bodyValue(requestValue) -// .accept(MediaType.TEXT_EVENT_STREAM) -// .retrieve() -// .bodyToFlux(String.class); -// -// return eventStream; -// } // 단답 답변 public String getChatResponse(String prompt) { - System.out.print(apiKey); - // ChatGPT에 질문 전송 - return chatgptService.sendMessage(prompt); + try{ + String prompt_guide= + "너는 지금 청년들의 금융 지식을 향상시켜주기 위한 챗봇이야. 너의 이름은 '금토리'야. 너는 캐릭터의 역할이기 때문에 텍스트 형식으로 답변을 해야 해. 언어는 한국어로 말해야 하고, 말투는 친구한테 말하는 것처럼 반발로 해." + + "그리고 금융에 관련된 답변만 해야 하고, 만약 금융과 관련이 없는 질문이면 '미안해. 금융과 관련되지 않은 질문은 답변해줄 수 없어.'라고 말하면 돼. " + + "질문은 다음과 같아. 실제로 사용자와 대화하듯이 말해야 하고, 바로 질문에 대한 답을 해. 상식적으로 알 수도 있다는 말은 하지 마." + + "'네'라는 대답은 하지마. 인사말도 하지 마. 그리고 최대한 자세하게 답변해. 다시 한 번 말하지만, 반말로 말해. 그리고 문장은 끝까지 완전한 형태로 말 해"; + prompt=prompt_guide.concat(prompt); + String response=chatgptService.sendMessage(prompt); + return response; + } + catch (Exception e){ + e.printStackTrace(); + return "request error"; + } } + } diff --git a/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java index b10657b..6fbd839 100644 --- a/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java +++ b/src/main/java/com/finfellows/domain/chatgpt/presentation/ChatGptController.java @@ -1,6 +1,10 @@ package com.finfellows.domain.chatgpt.presentation; import com.finfellows.domain.chatgpt.application.ChatGptService; +import com.finfellows.domain.comment.application.CommentService; +import com.finfellows.domain.comment.domain.QComment; +import com.finfellows.global.config.security.token.CurrentUser; +import com.finfellows.global.config.security.token.UserPrincipal; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.PostMapping; @@ -14,24 +18,21 @@ @Slf4j public class ChatGptController { private final ChatGptService chatgptService; - -// @PostMapping(value="/ask-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) -// public Flux ask(Locale locale, -// HttpServletRequest request, -// HttpServletResponse response, -// @RequestBody ChatgptQuestionRequest chatGptQuestionRequest){ -// try { -// return chatgptService.ask(chatGptQuestionRequest); -// }catch (JsonProcessingException je){ -// log.error(je.getMessage()); -// return Flux.empty(); -// } -// } + private final CommentService commentService; // 단답 테스트 // https://yjkim-dev.tistory.com/56 - @PostMapping("") + @PostMapping("/test") public String test(@RequestBody String question) { return chatgptService.getChatResponse(question); } + + // 답변 저장 테스트 + @PostMapping("") + public String getChatResponse(@CurrentUser UserPrincipal userPrincipal, @RequestBody String question){ + String answer= commentService.getChatResponse(question); + commentService.saveComment(userPrincipal.getId(), question, answer); + return answer; + } + } \ No newline at end of file diff --git a/src/main/java/com/finfellows/domain/comment/application/CommentService.java b/src/main/java/com/finfellows/domain/comment/application/CommentService.java index da5d479..7fd7382 100644 --- a/src/main/java/com/finfellows/domain/comment/application/CommentService.java +++ b/src/main/java/com/finfellows/domain/comment/application/CommentService.java @@ -1,6 +1,8 @@ package com.finfellows.domain.comment.application; +import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.PropertyNamingStrategies; import com.finfellows.domain.chatgpt.domain.ChatGptMessage; @@ -9,7 +11,10 @@ import com.finfellows.domain.chatgpt.dto.request.ChatgptQuestionRequest; import com.finfellows.domain.chatgpt.dto.request.ChatgptRequest; import com.finfellows.domain.chatgpt.dto.response.ChatgptResponse; +import com.finfellows.domain.comment.domain.Comment; import com.finfellows.domain.comment.domain.repository.CommentRepository; +import com.finfellows.domain.comment.dto.response.CommentResponse; +import com.finfellows.domain.user.domain.User; import com.finfellows.domain.user.domain.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; @@ -20,6 +25,7 @@ import org.springframework.web.client.RestTemplate; import java.util.*; +import java.util.stream.Collectors; @Service @RequiredArgsConstructor @@ -31,6 +37,7 @@ public class CommentService { @Autowired private RestTemplate restTemplate; + @Value("${chatgpt.api-key}") private String apiKey; private final ObjectMapper objectMapper = new ObjectMapper() @@ -47,7 +54,6 @@ public HttpEntity buildHttpEntity(ChatgptRequest chatGptRequest) // gpt 단답 public ChatgptResponse getResponse(HttpEntity chatGptRequestHttpEntity) { - SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory(); requestFactory.setConnectTimeout(60000); //답변이 길어질 경우 TimeOut Error가 발생하니 1분정도 설정해줍니다. @@ -81,4 +87,61 @@ public ChatgptResponse askQuestion(ChatgptQuestionRequest questionRequest) { ) ); } + + public String getChatResponse(String question){ + String responseFromGPT=chatGptService.getChatResponse(question); + return responseFromGPT; + } + + public void saveComment(Long userId, String question, String answer) { + Optional optionalUser = userRepository.findById(userId); + User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found")); + + question = extractPromptFromJson(question); + answer = answer.replaceAll("\\n", ""); + answer = answer.replaceAll("금토리: ", ""); + answer = answer.replaceAll("네. ", ""); + + Comment comment = Comment.builder() + .question(question) + .answer(answer) + .user(user) + .build(); + commentRepository.save(comment); + } + + // JSON에서 "prompt" 부분 추출하는 메소드 + private String extractPromptFromJson(String json) { + try { + ObjectMapper objectMapper = new ObjectMapper(); + JsonNode jsonNode = objectMapper.readTree(json); + if (jsonNode.has("prompt")) { + return jsonNode.get("prompt").asText(); + } + } catch (JsonProcessingException e) { + System.out.print("텍스트 변환 실패"); + } + return json; + } + + public List getAllComments(Long userId) { + List comments = commentRepository.findAllByUserId(userId); + + Comment greet = Comment.builder() + .greeting("안녕! 나는 금토리야. 도움이 필요하다면 편하게 말해줘.") + .build(); + commentRepository.save(greet); + + return comments.stream() + .map(comment -> CommentResponse.builder() + .commentId(comment.getCommentId()) + .created_at(comment.getCreatedAt()) + .greeting(comment.getGreeting()) + .question(comment.getQuestion()) + .answer(comment.getAnswer()) + .userId(comment.getUser()) + .build() + ) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/com/finfellows/domain/comment/domain/Comment.java b/src/main/java/com/finfellows/domain/comment/domain/Comment.java index 00c31c2..6c46e68 100644 --- a/src/main/java/com/finfellows/domain/comment/domain/Comment.java +++ b/src/main/java/com/finfellows/domain/comment/domain/Comment.java @@ -11,23 +11,29 @@ @Getter public class Comment extends BaseEntity { - //질문 내용 저장 칼럼 필요함. @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="comment_id", updatable = false, nullable = false, unique = true) private Long commentId; - @Column(name="comment_content") - private String commentContent; + @Column(name = "greeting") + private String greeting; + + @Column(name = "question") + private String question; + + @Column(name="answer") + private String answer; @ManyToOne @JoinColumn(name="user_id") - private User userId; + private User user; @Builder - public Comment(Long commentId, String commentContent, User userId){ - this.commentId=commentId; - this.commentContent=commentContent; - this.userId=userId; + public Comment(String question, String greeting, String answer, User user){ + this.greeting=greeting; + this.question=question; + this.answer=answer; + this.user=user; } } diff --git a/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java b/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java index ec86eae..a588cd4 100644 --- a/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java +++ b/src/main/java/com/finfellows/domain/comment/domain/repository/CommentRepository.java @@ -2,6 +2,11 @@ import com.finfellows.domain.comment.domain.Comment; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import java.util.List; + +@Repository public interface CommentRepository extends JpaRepository { + List findAllByUserId(Long userId); } diff --git a/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java b/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java new file mode 100644 index 0000000..84472d8 --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java @@ -0,0 +1,22 @@ +package com.finfellows.domain.comment.dto.request; + +import com.finfellows.domain.user.domain.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CommentRequest { + private Long commentId; + private LocalDateTime created_at; + private String greeting; + private String question; + private String answer; + private User userId; +} diff --git a/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java b/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java new file mode 100644 index 0000000..1a581b5 --- /dev/null +++ b/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java @@ -0,0 +1,22 @@ +package com.finfellows.domain.comment.dto.response; + +import com.finfellows.domain.user.domain.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CommentResponse { + private Long commentId; + private LocalDateTime created_at; + private String greeting; + private String question; + private String answer; + private User userId; +} diff --git a/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java index 4bcc573..f53c267 100644 --- a/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java @@ -1,9 +1,46 @@ package com.finfellows.domain.comment.presentation; +import com.finfellows.domain.chatgpt.application.ChatGptService; +import com.finfellows.domain.comment.application.CommentService; +import com.finfellows.domain.comment.dto.response.CommentResponse; +import com.finfellows.domain.user.application.UserService; +import com.finfellows.global.config.security.token.CurrentUser; +import com.finfellows.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequiredArgsConstructor +@RequestMapping("/api/chatbot") +@Tag(name="Chatbot",description = "Chatbot API") public class CommentController { + private CommentService commentService; + private ChatGptService chatGptService; + private UserService userService; + + + @Autowired + public CommentController(CommentService commentService, ChatGptService chatGptService, UserService userService) { + this.commentService = commentService; + this.chatGptService = chatGptService; + this.userService = userService; + } + + @PostMapping("") + public String getChatResponse(@CurrentUser UserPrincipal userPrincipal, @RequestBody String question){ + String answer= commentService.getChatResponse(question); + commentService.saveComment(userPrincipal.getId(), question, answer); + return answer; + } + @GetMapping("") + public ResponseEntity> getAllComments(@CurrentUser UserPrincipal userPrincipal){ + List responseList=commentService.getAllComments(userPrincipal.getId()); + return new ResponseEntity<>(responseList, HttpStatus.OK); + } } diff --git a/src/main/java/com/finfellows/global/config/security/SecurityConfig.java b/src/main/java/com/finfellows/global/config/security/SecurityConfig.java index a4cce10..2752ab4 100644 --- a/src/main/java/com/finfellows/global/config/security/SecurityConfig.java +++ b/src/main/java/com/finfellows/global/config/security/SecurityConfig.java @@ -68,6 +68,9 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/api/v1/chat-gpt") .permitAll() + .requestMatchers("/api/chatbot") + .permitAll() + .anyRequest() .authenticated()); From f09fb0da537a095738b5801491d495789f2e7128 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 03:40:47 +0900 Subject: [PATCH 19/25] =?UTF-8?q?[FEAT]=20educontent=20created=5Fat=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD/=EC=9D=91=EB=8B=B5=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/educontent/dto/request/EduContentRequest.java | 3 +++ .../domain/educontent/dto/response/EduContentResponse.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java index 130e9e0..e8c2b3c 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java @@ -5,12 +5,15 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; + @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class EduContentRequest { private Long id; + private LocalDateTime created_at; private String title; private String content; } diff --git a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java index d711383..a2231c6 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java @@ -5,12 +5,15 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; + @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class EduContentResponse { private Long id; + private LocalDateTime created_at; private String title; private String content; } From 7154a1e6c85e710464b7956b4ab117d55fdbb8d2 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 04:28:21 +0900 Subject: [PATCH 20/25] =?UTF-8?q?[FIX]=20#39=20=EC=B1=97=EB=B4=87=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD/=EC=9D=91=EB=8B=B5=EA=B0=92=20UserId=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finfellows/domain/comment/application/CommentService.java | 2 +- .../finfellows/domain/comment/dto/request/CommentRequest.java | 2 +- .../finfellows/domain/comment/dto/response/CommentResponse.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/finfellows/domain/comment/application/CommentService.java b/src/main/java/com/finfellows/domain/comment/application/CommentService.java index 7fd7382..9c41910 100644 --- a/src/main/java/com/finfellows/domain/comment/application/CommentService.java +++ b/src/main/java/com/finfellows/domain/comment/application/CommentService.java @@ -139,7 +139,7 @@ public List getAllComments(Long userId) { .greeting(comment.getGreeting()) .question(comment.getQuestion()) .answer(comment.getAnswer()) - .userId(comment.getUser()) + .userId(comment.getUser().getId()) .build() ) .collect(Collectors.toList()); diff --git a/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java b/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java index 84472d8..801ea38 100644 --- a/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java +++ b/src/main/java/com/finfellows/domain/comment/dto/request/CommentRequest.java @@ -18,5 +18,5 @@ public class CommentRequest { private String greeting; private String question; private String answer; - private User userId; + private Long userId; } diff --git a/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java b/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java index 1a581b5..e110023 100644 --- a/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java +++ b/src/main/java/com/finfellows/domain/comment/dto/response/CommentResponse.java @@ -18,5 +18,5 @@ public class CommentResponse { private String greeting; private String question; private String answer; - private User userId; + private Long userId; } From 5b17854d4bfe03927981d79bf9ad1f3f9a39b4fb Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 04:35:11 +0900 Subject: [PATCH 21/25] =?UTF-8?q?[FIX]=20#39=20=EC=B1=97=EB=B4=87=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD/=EC=9D=91=EB=8B=B5=EA=B0=92=20UserId=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finfellows/domain/comment/application/CommentService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/finfellows/domain/comment/application/CommentService.java b/src/main/java/com/finfellows/domain/comment/application/CommentService.java index 9c41910..605921d 100644 --- a/src/main/java/com/finfellows/domain/comment/application/CommentService.java +++ b/src/main/java/com/finfellows/domain/comment/application/CommentService.java @@ -125,10 +125,14 @@ private String extractPromptFromJson(String json) { } public List getAllComments(Long userId) { + Optional optionalUser = userRepository.findById(userId); + User user = optionalUser.orElseThrow(() -> new RuntimeException("User not found")); + List comments = commentRepository.findAllByUserId(userId); Comment greet = Comment.builder() .greeting("안녕! 나는 금토리야. 도움이 필요하다면 편하게 말해줘.") + .user(user) .build(); commentRepository.save(greet); From d02232fccd2b63bdf6757005a331b3f6bc0a58b7 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 14:12:16 +0900 Subject: [PATCH 22/25] =?UTF-8?q?[FIX]=20#39=20swagger=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/presentation/CommentController.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java index f53c267..b1adb25 100644 --- a/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java +++ b/src/main/java/com/finfellows/domain/comment/presentation/CommentController.java @@ -6,6 +6,11 @@ import com.finfellows.domain.user.application.UserService; import com.finfellows.global.config.security.token.CurrentUser; import com.finfellows.global.config.security.token.UserPrincipal; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; @@ -32,12 +37,21 @@ public CommentController(CommentService commentService, ChatGptService chatGptSe this.userService = userService; } + @Operation(summary = "챗봇 질의응답 저장", description = "챗봇 질문과 답변을 저장합니다.") + @ApiResponse(responseCode = "200", description = "챗봇 질문에 대한 답변 응답 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = CommentResponse.class))) + }) @PostMapping("") public String getChatResponse(@CurrentUser UserPrincipal userPrincipal, @RequestBody String question){ String answer= commentService.getChatResponse(question); commentService.saveComment(userPrincipal.getId(), question, answer); return answer; } + + @Operation(summary = "챗봇 대화 내용 조회", description = "챗봇 대화 전체 목록을 조회합니다.") + @ApiResponse(responseCode = "200", description = "챗봇 대화 목록 조회 성공", content = { + @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = CommentResponse.class))) + }) @GetMapping("") public ResponseEntity> getAllComments(@CurrentUser UserPrincipal userPrincipal){ List responseList=commentService.getAllComments(userPrincipal.getId()); From 4fa0feba22ccfcdfc01e94dbd61f1d3343df68e1 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Sun, 7 Jan 2024 14:56:28 +0900 Subject: [PATCH 23/25] =?UTF-8?q?[FIX]=20#52=20Post=20Entity=20enum=20type?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../finfellows/domain/educontent/domain/EduContent.java | 5 +++++ .../finfellows/domain/newscontent/domain/NewsContent.java | 6 ++++++ .../java/com/finfellows/domain/post/domain/Content.java | 4 ++++ .../com/finfellows/domain/post/domain/ContentType.java | 7 +++++++ src/main/java/com/finfellows/domain/post/domain/Post.java | 7 ++++++- 5 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/finfellows/domain/post/domain/ContentType.java diff --git a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java index 420223b..6988580 100644 --- a/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java +++ b/src/main/java/com/finfellows/domain/educontent/domain/EduContent.java @@ -1,6 +1,7 @@ package com.finfellows.domain.educontent.domain; import com.finfellows.domain.common.BaseEntity; +import com.finfellows.domain.post.domain.ContentType; import com.finfellows.domain.post.domain.Post; import jakarta.persistence.*; import lombok.AccessLevel; @@ -25,6 +26,9 @@ public class EduContent extends BaseEntity { @JoinColumn(name="post_id") private Post post; + @Enumerated(EnumType.STRING) + @Column(name="contentType") + private ContentType contentType; @Column(name="title") private String title; @@ -37,6 +41,7 @@ public EduContent(Post post, String title, String content){ this.post=post; this.title=title; this.content=content; + this.contentType = ContentType.EDU_CONTENT; } public void updateContent(String title, String content) { diff --git a/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java b/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java index 5d6006c..eced305 100644 --- a/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java +++ b/src/main/java/com/finfellows/domain/newscontent/domain/NewsContent.java @@ -1,6 +1,7 @@ package com.finfellows.domain.newscontent.domain; import com.finfellows.domain.common.BaseEntity; +import com.finfellows.domain.post.domain.ContentType; import com.finfellows.domain.post.domain.Post; import jakarta.persistence.*; import lombok.Builder; @@ -29,11 +30,16 @@ public class NewsContent extends BaseEntity { @Column(name="content") private String content; + @Enumerated(EnumType.STRING) + @Column(name="contentType") + private ContentType contentType; + @Builder public NewsContent(Post post, String title, String content){ this.post=post; this.title=title; this.content=content; + this.contentType = ContentType.NEWS_CONTENT; } public void updateContent(String title, String content) { diff --git a/src/main/java/com/finfellows/domain/post/domain/Content.java b/src/main/java/com/finfellows/domain/post/domain/Content.java index c5f3db5..471a7b5 100644 --- a/src/main/java/com/finfellows/domain/post/domain/Content.java +++ b/src/main/java/com/finfellows/domain/post/domain/Content.java @@ -32,12 +32,16 @@ public class Content { @Column(name="content") private String content; + @Enumerated(EnumType.STRING) + @Column(name="contentType") + private ContentType contentType; @Builder public Content(Post post_id, String title, String content){ this.post_id=post_id; this.title=title; this.content=content; + this.contentType = ContentType.CONTENT; } public void updateContent(String title, String content) { diff --git a/src/main/java/com/finfellows/domain/post/domain/ContentType.java b/src/main/java/com/finfellows/domain/post/domain/ContentType.java new file mode 100644 index 0000000..a0f2316 --- /dev/null +++ b/src/main/java/com/finfellows/domain/post/domain/ContentType.java @@ -0,0 +1,7 @@ +package com.finfellows.domain.post.domain; + +public enum ContentType { + EDU_CONTENT, + NEWS_CONTENT, + CONTENT +} diff --git a/src/main/java/com/finfellows/domain/post/domain/Post.java b/src/main/java/com/finfellows/domain/post/domain/Post.java index 5231c18..f661ccf 100644 --- a/src/main/java/com/finfellows/domain/post/domain/Post.java +++ b/src/main/java/com/finfellows/domain/post/domain/Post.java @@ -26,9 +26,14 @@ public class Post extends BaseEntity { @JoinColumn(name="writer_id") private User writer; + @Enumerated(EnumType.STRING) + @Column(name="contentType") + private ContentType contentType; + @Builder - public Post(User writer){ + public Post(User writer, ContentType contentType){ this.writer=writer; + this.contentType=contentType; } } From 65dfee208a89086c9fcfca5bbea12d3e4ddf70ac Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Mon, 8 Jan 2024 17:45:01 +0900 Subject: [PATCH 24/25] =?UTF-8?q?[FIX]=20#54=20=EA=B8=88=EC=9C=B5=20?= =?UTF-8?q?=EB=B0=B0=EC=9A=B0=EC=9E=90=20=EB=B6=81=EB=A7=88=ED=81=AC=20?= =?UTF-8?q?=EC=97=AC=EB=B6=80=20Response=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/EduContentBookmarkRepository.java | 2 ++ .../educontent/application/EduContentService.java | 10 +++++++++- .../educontent/dto/response/EduContentResponse.java | 1 + .../presentation/EduContentController.java | 6 ++++-- .../newscontent/application/NewsContentService.java | 12 +++++++++++- .../dto/response/NewsContentResponse.java | 1 + .../presentation/NewsContentController.java | 6 ++++-- 7 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/finfellows/domain/bookmark/domain/repository/EduContentBookmarkRepository.java b/src/main/java/com/finfellows/domain/bookmark/domain/repository/EduContentBookmarkRepository.java index 8d147e8..e64fb22 100644 --- a/src/main/java/com/finfellows/domain/bookmark/domain/repository/EduContentBookmarkRepository.java +++ b/src/main/java/com/finfellows/domain/bookmark/domain/repository/EduContentBookmarkRepository.java @@ -13,4 +13,6 @@ public interface EduContentBookmarkRepository extends JpaRepository findByUserAndEduContent(User user, EduContent eduContent); List findAllByUser(User user); + + boolean existsByUser_IdAndEduContent_Id(Long userId, Long id); } diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index 437605e..1b31cf0 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -1,5 +1,6 @@ package com.finfellows.domain.educontent.application; +import com.finfellows.domain.bookmark.domain.repository.EduContentBookmarkRepository; import com.finfellows.domain.educontent.domain.EduContent; import com.finfellows.domain.educontent.domain.repository.EduContentRepository; import com.finfellows.domain.educontent.dto.request.EduContentRequest; @@ -20,6 +21,7 @@ public class EduContentService { private final EduContentRepository eduContentRepository; private final PostRepository postRepository; + private final EduContentBookmarkRepository eduContentBookmarkRepository; @Transactional public EduContent createEduContent(EduContentResponse request) { @@ -38,13 +40,14 @@ public EduContent createEduContent(EduContentResponse request) { return savedContent; } - public List getAllEduContents() { + public List getAllEduContents(Long userId) { List eduContents = eduContentRepository.findAll(); return eduContents.stream() .map(eduContent -> EduContentResponse.builder() .id(eduContent.getId()) .title(eduContent.getTitle()) .content(eduContent.getContent()) + .bookmarked(checkBookmarked(userId, eduContent.getId())) .build()) .collect(Collectors.toList()); } @@ -83,4 +86,9 @@ public EduContentResponse updateEduContent(Long id, EduContentRequest request) { .content(updatedContent.getContent()) .build(); } + + + private boolean checkBookmarked(Long userId, Long eduContentId) { + return eduContentBookmarkRepository.existsByUser_IdAndEduContent_Id(userId, eduContentId); + } } diff --git a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java index a2231c6..d8fbe32 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/response/EduContentResponse.java @@ -16,4 +16,5 @@ public class EduContentResponse { private LocalDateTime created_at; private String title; private String content; + private boolean bookmarked; } diff --git a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java index c9fa017..2ba981b 100644 --- a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java +++ b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java @@ -4,6 +4,8 @@ import com.finfellows.domain.educontent.domain.EduContent; import com.finfellows.domain.educontent.dto.request.EduContentRequest; import com.finfellows.domain.educontent.dto.response.EduContentResponse; +import com.finfellows.global.config.security.token.CurrentUser; +import com.finfellows.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -39,8 +41,8 @@ public ResponseEntity saveEduContent(@RequestBody EduContentResponse @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = EduContentResponse.class))) }) @GetMapping - public ResponseEntity> getAllEduContents() { - List responseList = eduContentService.getAllEduContents(); + public ResponseEntity> getAllEduContents(@CurrentUser UserPrincipal userPrincipal) { + List responseList = eduContentService.getAllEduContents(userPrincipal.getId()); return new ResponseEntity<>(responseList, HttpStatus.OK); } diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index c6e0891..182861b 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -1,11 +1,14 @@ package com.finfellows.domain.newscontent.application; +import com.finfellows.domain.bookmark.domain.repository.EduContentBookmarkRepository; +import com.finfellows.domain.educontent.domain.EduContent; import com.finfellows.domain.newscontent.domain.NewsContent; import com.finfellows.domain.newscontent.domain.repository.NewsContentRepository; import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; import com.finfellows.domain.newscontent.dto.response.NewsContentResponse; import com.finfellows.domain.post.domain.Post; import com.finfellows.domain.post.domain.repository.PostRepository; +import com.finfellows.domain.user.domain.repository.UserRepository; import jakarta.persistence.EntityNotFoundException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -20,6 +23,7 @@ public class NewsContentService { private final NewsContentRepository newsContentRepository; private final PostRepository postRepository; + private final EduContentBookmarkRepository eduContentBookmarkRepository; @Transactional public NewsContent createNewsContent(NewsContentResponse request) { @@ -38,13 +42,14 @@ public NewsContent createNewsContent(NewsContentResponse request) { return savedContent; } - public List getAllNewsContents() { + public List getAllNewsContents(Long userId) { List newsContents = newsContentRepository.findAll(); return newsContents.stream() .map(newsContent -> NewsContentResponse.builder() .id(newsContent.getId()) .title(newsContent.getTitle()) .content(newsContent.getContent()) + .bookmarked(checkBookmarked(userId, newsContent.getId())) // 북마크 여부 확인 .build()) .collect(Collectors.toList()); } @@ -83,4 +88,9 @@ public NewsContentResponse updateNewsContent(Long id, NewsContentRequest request .content(updatedContent.getContent()) .build(); } + + // 특정 뉴스 콘텐츠에 대한 북마크 여부 확인 + private boolean checkBookmarked(Long userId, Long newsContentId) { + return eduContentBookmarkRepository.existsByUser_IdAndEduContent_Id(userId, newsContentId); + } } diff --git a/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java b/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java index 584e34c..aa3b6e7 100644 --- a/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java +++ b/src/main/java/com/finfellows/domain/newscontent/dto/response/NewsContentResponse.java @@ -13,4 +13,5 @@ public class NewsContentResponse { private Long id; private String title; private String content; + private boolean bookmarked; } diff --git a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java index db28bc3..16903a5 100644 --- a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java +++ b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java @@ -4,6 +4,8 @@ import com.finfellows.domain.newscontent.domain.NewsContent; import com.finfellows.domain.newscontent.dto.request.NewsContentRequest; import com.finfellows.domain.newscontent.dto.response.NewsContentResponse; +import com.finfellows.global.config.security.token.CurrentUser; +import com.finfellows.global.config.security.token.UserPrincipal; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.media.ArraySchema; import io.swagger.v3.oas.annotations.media.Content; @@ -39,8 +41,8 @@ public ResponseEntity saveNewsContent(@RequestBody NewsContentRespo @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = NewsContentResponse.class))) }) @GetMapping - public ResponseEntity> getAllNewsContents() { - List responseList = newsContentService.getAllNewsContents(); + public ResponseEntity> getAllNewsContents(@CurrentUser UserPrincipal userPrincipal) { + List responseList = newsContentService.getAllNewsContents(userPrincipal.getId()); return new ResponseEntity<>(responseList, HttpStatus.OK); } From 38f2938a41b761286843b66f9c459917bd73ee72 Mon Sep 17 00:00:00 2001 From: EunbeenDev Date: Wed, 10 Jan 2024 01:18:06 +0900 Subject: [PATCH 25/25] =?UTF-8?q?[FIX]=20#83=20Content,=20EduContent,=20Ne?= =?UTF-8?q?wsContent=20Request=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit id request 삭제 --- .../domain/educontent/application/EduContentService.java | 2 +- .../domain/educontent/dto/request/EduContentRequest.java | 1 - .../domain/educontent/presentation/EduContentController.java | 2 +- .../domain/newscontent/application/NewsContentService.java | 2 +- .../domain/newscontent/dto/request/NewsContentRequest.java | 4 +++- .../newscontent/presentation/NewsContentController.java | 2 +- .../finfellows/domain/post/application/ContentService.java | 2 +- .../finfellows/domain/post/dto/request/ContentRequest.java | 1 - .../domain/post/presentation/ContentController.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java index 1b31cf0..02ec250 100644 --- a/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java +++ b/src/main/java/com/finfellows/domain/educontent/application/EduContentService.java @@ -24,7 +24,7 @@ public class EduContentService { private final EduContentBookmarkRepository eduContentBookmarkRepository; @Transactional - public EduContent createEduContent(EduContentResponse request) { + public EduContent createEduContent(EduContentRequest request) { Post post = new Post(); postRepository.save(post); diff --git a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java index e8c2b3c..9ab7ca6 100644 --- a/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java +++ b/src/main/java/com/finfellows/domain/educontent/dto/request/EduContentRequest.java @@ -12,7 +12,6 @@ @AllArgsConstructor @NoArgsConstructor public class EduContentRequest { - private Long id; private LocalDateTime created_at; private String title; private String content; diff --git a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java index 2ba981b..6052cb5 100644 --- a/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java +++ b/src/main/java/com/finfellows/domain/educontent/presentation/EduContentController.java @@ -31,7 +31,7 @@ public class EduContentController { @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = EduContentResponse.class))) }) @PostMapping("") - public ResponseEntity saveEduContent(@RequestBody EduContentResponse request) { + public ResponseEntity saveEduContent(@RequestBody EduContentRequest request) { EduContent response = eduContentService.createEduContent(request); return new ResponseEntity<>(response, HttpStatus.CREATED); } diff --git a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java index 182861b..124feb5 100644 --- a/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java +++ b/src/main/java/com/finfellows/domain/newscontent/application/NewsContentService.java @@ -26,7 +26,7 @@ public class NewsContentService { private final EduContentBookmarkRepository eduContentBookmarkRepository; @Transactional - public NewsContent createNewsContent(NewsContentResponse request) { + public NewsContent createNewsContent(NewsContentRequest request) { Post post = new Post(); postRepository.save(post); diff --git a/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java b/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java index 40066a1..dcb2288 100644 --- a/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java +++ b/src/main/java/com/finfellows/domain/newscontent/dto/request/NewsContentRequest.java @@ -5,12 +5,14 @@ import lombok.Getter; import lombok.NoArgsConstructor; +import java.time.LocalDateTime; + @Getter @Builder @AllArgsConstructor @NoArgsConstructor public class NewsContentRequest { - private Long id; + private LocalDateTime created_at; private String title; private String content; } diff --git a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java index 16903a5..c36877f 100644 --- a/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java +++ b/src/main/java/com/finfellows/domain/newscontent/presentation/NewsContentController.java @@ -31,7 +31,7 @@ public class NewsContentController { @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = NewsContentResponse.class))) }) @PostMapping("") - public ResponseEntity saveNewsContent(@RequestBody NewsContentResponse request) { + public ResponseEntity saveNewsContent(@RequestBody NewsContentRequest request) { NewsContent response = newsContentService.createNewsContent(request); return new ResponseEntity<>(response, HttpStatus.CREATED); } diff --git a/src/main/java/com/finfellows/domain/post/application/ContentService.java b/src/main/java/com/finfellows/domain/post/application/ContentService.java index b73ef7a..4281918 100644 --- a/src/main/java/com/finfellows/domain/post/application/ContentService.java +++ b/src/main/java/com/finfellows/domain/post/application/ContentService.java @@ -22,7 +22,7 @@ public class ContentService { private final PostRepository postRepository; @Transactional - public Content createContent(ContentResponse request) { + public Content createContent(ContentRequest request) { Post post = new Post(); postRepository.save(post); diff --git a/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java b/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java index 877e00b..0764cf6 100644 --- a/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java +++ b/src/main/java/com/finfellows/domain/post/dto/request/ContentRequest.java @@ -11,7 +11,6 @@ @AllArgsConstructor @NoArgsConstructor public class ContentRequest { - private Long id; private LocalDateTime created_at; private String title; private String content; diff --git a/src/main/java/com/finfellows/domain/post/presentation/ContentController.java b/src/main/java/com/finfellows/domain/post/presentation/ContentController.java index 9ebf354..e658223 100644 --- a/src/main/java/com/finfellows/domain/post/presentation/ContentController.java +++ b/src/main/java/com/finfellows/domain/post/presentation/ContentController.java @@ -30,7 +30,7 @@ public class ContentController { @Content(mediaType = "application/json", array = @ArraySchema(schema = @Schema(implementation = ContentResponse.class))) }) @PostMapping("") - public ResponseEntity saveContent(@RequestBody ContentResponse request) { + public ResponseEntity saveContent(@RequestBody ContentRequest request) { com.finfellows.domain.post.domain.Content response = contentService.createContent(request); return new ResponseEntity<>(response, HttpStatus.CREATED); }