diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 9bb2d5f..4e70acb 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -43,6 +43,8 @@ jobs: echo "${{ secrets.APPLICATION_OAUTH2_YML }}" | base64 --decode > src/main/resources/oauth2/application-oauth2.yml mkdir -p src/main/resources/s3 echo "${{ secrets.APPLICATION_S3_YML }}" | base64 --decode > src/main/resources/s3/application-s3.yml + mkdir -p src/main/resources/chatgpt + echo "${{ secrets.APPLICATION_CHATGPT_YML }}" | base64 --decode > src/main/resources/chatgpt/application-chatgpt.yml # (4) Gradle build (Test 제외) diff --git a/src/main/java/com/example/ai_tutor/domain/note/application/NoteService.java b/src/main/java/com/example/ai_tutor/domain/note/application/NoteService.java index 336921a..4dd20a7 100644 --- a/src/main/java/com/example/ai_tutor/domain/note/application/NoteService.java +++ b/src/main/java/com/example/ai_tutor/domain/note/application/NoteService.java @@ -29,6 +29,7 @@ import com.amazonaws.services.s3.model.PutObjectRequest; import java.io.IOException; +import java.util.Comparator; import java.util.List; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; @@ -147,11 +148,26 @@ public ResponseEntity getStepOne(UserPrincipal userPrincipal, Long noteId) { List text = textRepository.findAllByNote(note); List summary = summaryRepository.findAllByNote(note); + // summaryId 기준으로 정렬 + List sortedText = text.stream() + .sorted(Comparator.comparing(t -> summary.stream() + .filter(s -> s.getSummaryId().equals(t.getTextId())) + .findFirst() + .map(Summary::getSummaryId) + .orElse(null))) + .collect(Collectors.toList()); + + // textId를 순차적으로 부여 AtomicInteger counter = new AtomicInteger(1); - List stepOneRes = text.stream() + List stepOneRes = sortedText.stream() .map(t -> StepOneRes.builder() - .textId(counter.getAndIncrement()) //1부터 증가 + .textId(counter.getAndIncrement()) // 1부터 증가 .content(t.getContent()) + .summaryId(summary.stream() + .filter(s -> s.getSummaryId().equals(t.getTextId())) + .findFirst() + .map(Summary::getSummaryId) + .orElse(null)) .summary(summary.stream() .filter(s -> s.getSummaryId().equals(t.getTextId())) .findFirst() @@ -160,7 +176,7 @@ public ResponseEntity getStepOne(UserPrincipal userPrincipal, Long noteId) { .build()) .collect(Collectors.toList()); - StepOneListRes stepOneListRes=StepOneListRes.builder() + StepOneListRes stepOneListRes = StepOneListRes.builder() .stepOneRes(stepOneRes) .build(); diff --git a/src/main/java/com/example/ai_tutor/domain/note/domain/Note.java b/src/main/java/com/example/ai_tutor/domain/note/domain/Note.java index 30ca701..909f84b 100644 --- a/src/main/java/com/example/ai_tutor/domain/note/domain/Note.java +++ b/src/main/java/com/example/ai_tutor/domain/note/domain/Note.java @@ -55,7 +55,7 @@ public class Note extends BaseEntity { // 원본 텍스트 @Lob - @Column(name="original_text") + @Column(name="original_text", columnDefinition = "TEXT") private String originalText; // @OneToMany(mappedBy = "note") diff --git a/src/main/java/com/example/ai_tutor/domain/note/domain/repository/NoteRepository.java b/src/main/java/com/example/ai_tutor/domain/note/domain/repository/NoteRepository.java index 016b5ba..a84a0e8 100644 --- a/src/main/java/com/example/ai_tutor/domain/note/domain/repository/NoteRepository.java +++ b/src/main/java/com/example/ai_tutor/domain/note/domain/repository/NoteRepository.java @@ -10,4 +10,4 @@ @Repository public interface NoteRepository extends JpaRepository { List findAllByFolder(Folder folder); -} +} \ No newline at end of file diff --git a/src/main/java/com/example/ai_tutor/domain/note/dto/response/StepOneRes.java b/src/main/java/com/example/ai_tutor/domain/note/dto/response/StepOneRes.java index 1106564..6615918 100644 --- a/src/main/java/com/example/ai_tutor/domain/note/dto/response/StepOneRes.java +++ b/src/main/java/com/example/ai_tutor/domain/note/dto/response/StepOneRes.java @@ -11,6 +11,7 @@ @Getter public class StepOneRes { private int textId; //문단 번호이므로 int로 처리 - private String content; - private String summary; + private String content; //원문 내용 + private Long summaryId; //요약문 id + private String summary; //요약문 내용 } diff --git a/src/main/java/com/example/ai_tutor/domain/practice/application/PracticeService.java b/src/main/java/com/example/ai_tutor/domain/practice/application/PracticeService.java index 0f14faf..9e8be80 100644 --- a/src/main/java/com/example/ai_tutor/domain/practice/application/PracticeService.java +++ b/src/main/java/com/example/ai_tutor/domain/practice/application/PracticeService.java @@ -103,6 +103,8 @@ public ResponseEntity getQuestionsAndAnswers(UserPrincipal userPrincipal, Lon .sorted(Comparator.comparing(PracticeResultsRes::getSequence)) .collect(Collectors.toList()); + // test + ApiResponse apiResponse = ApiResponse.builder() .check(true) .information(practiceResultsRes) diff --git a/src/main/java/com/example/ai_tutor/domain/summary/application/SummaryService.java b/src/main/java/com/example/ai_tutor/domain/summary/application/SummaryService.java new file mode 100644 index 0000000..6f3605f --- /dev/null +++ b/src/main/java/com/example/ai_tutor/domain/summary/application/SummaryService.java @@ -0,0 +1,46 @@ +package com.example.ai_tutor.domain.summary.application; + +import com.example.ai_tutor.domain.Folder.domain.Folder; +import com.example.ai_tutor.domain.note.domain.Note; +import com.example.ai_tutor.domain.note.domain.repository.NoteRepository; +import com.example.ai_tutor.domain.summary.domain.Summary; +import com.example.ai_tutor.domain.summary.domain.repository.SummaryRepository; +import com.example.ai_tutor.domain.summary.dto.request.SummaryUpdateReq; +import com.example.ai_tutor.domain.user.domain.User; +import com.example.ai_tutor.domain.user.domain.repository.UserRepository; +import com.example.ai_tutor.global.DefaultAssert; +import com.example.ai_tutor.global.config.security.token.UserPrincipal; +import com.example.ai_tutor.global.payload.ApiResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@RequiredArgsConstructor +public class SummaryService { + private final UserRepository userRepository; + private final SummaryRepository summaryRepository; + private final NoteRepository noteRepository; + + @Transactional + public ResponseEntity updateSummary( + UserPrincipal userPrincipal, + Long noteId, Long summaryId, + SummaryUpdateReq summaryUpdateReq) { + User user = userRepository.findById(userPrincipal.getId()).orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + Note note = noteRepository.findById(noteId).orElseThrow(() -> new IllegalArgumentException("노트를 찾을 수 없습니다.")); + DefaultAssert.isTrue(note.getUser().equals(user), "해당 폴더에 접근할 수 없습니다."); + + String newSummary = summaryUpdateReq.getSummary(); + Summary summary = summaryRepository.findById(summaryId).orElseThrow(() -> new IllegalArgumentException("요약문을 찾을 수 없습니다.")); + summary.updateSummary(newSummary); + + ApiResponse apiResponse=ApiResponse.builder() + .check(true) + .information("요약문 수정 성공") + .build(); + + return ResponseEntity.ok(apiResponse); + } +} diff --git a/src/main/java/com/example/ai_tutor/domain/summary/domain/Summary.java b/src/main/java/com/example/ai_tutor/domain/summary/domain/Summary.java index 7b718aa..9b37207 100644 --- a/src/main/java/com/example/ai_tutor/domain/summary/domain/Summary.java +++ b/src/main/java/com/example/ai_tutor/domain/summary/domain/Summary.java @@ -49,4 +49,8 @@ public Summary(Text text, User user, Folder folder, Note note, String content){ this.note = note; this.content = content; } + + public void updateSummary(String newSummary) { + this.content = newSummary; + } } diff --git a/src/main/java/com/example/ai_tutor/domain/summary/dto/request/SummaryUpdateReq.java b/src/main/java/com/example/ai_tutor/domain/summary/dto/request/SummaryUpdateReq.java new file mode 100644 index 0000000..4795a64 --- /dev/null +++ b/src/main/java/com/example/ai_tutor/domain/summary/dto/request/SummaryUpdateReq.java @@ -0,0 +1,14 @@ +package com.example.ai_tutor.domain.summary.dto.request; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class SummaryUpdateReq { + private String summary; +} diff --git a/src/main/java/com/example/ai_tutor/domain/summary/presentation/SummaryController.java b/src/main/java/com/example/ai_tutor/domain/summary/presentation/SummaryController.java new file mode 100644 index 0000000..b3dc278 --- /dev/null +++ b/src/main/java/com/example/ai_tutor/domain/summary/presentation/SummaryController.java @@ -0,0 +1,42 @@ +package com.example.ai_tutor.domain.summary.presentation; + +import com.example.ai_tutor.domain.summary.application.SummaryService; +import com.example.ai_tutor.domain.summary.dto.request.SummaryUpdateReq; +import com.example.ai_tutor.global.config.security.token.CurrentUser; +import com.example.ai_tutor.global.config.security.token.UserPrincipal; +import com.example.ai_tutor.global.payload.ErrorResponse; +import com.example.ai_tutor.global.payload.Message; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +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.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/v1/note") +@Tag(name = "Summary", description = "요약문 관련 API입니다.") +public class SummaryController { + + private final SummaryService summaryService; + + @Operation(summary = "요약문 수정 API", description = "특정 강의 노트의 요약문 문단 하나를 수정하는 API입니다.") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "학습 단계 업데이트 성공", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = Message.class) ) } ), + @ApiResponse(responseCode = "400", description = "학습 단계 업데이트 실패", content = { @Content(mediaType = "application/json", schema = @Schema(implementation = ErrorResponse.class) ) } ), + }) + @PatchMapping("/{noteId}/step/1/{summaryId}") + public ResponseEntity updateStepOne( + @Parameter @CurrentUser UserPrincipal userPrincipal, + @PathVariable Long noteId, + @PathVariable Long summaryId, + @RequestBody SummaryUpdateReq summaryUpdateReq + ) { + return summaryService.updateSummary(userPrincipal, noteId, summaryId, summaryUpdateReq); + } +}