Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@ public class Summary extends BaseEntity {
@Column(columnDefinition = "TEXT", nullable = false)
private String content;

@Column(name = "selected")
@Column(nullable = false)
private boolean selected;

@Builder
public Summary(Link link, Format format, String content, boolean select) {
public Summary(Link link, Format format, String content, Boolean selected) {
this.link = link;
this.format = format;
this.content = content;
this.selected = select;
this.selected = selected != null && selected;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.sofa.linkiving.domain.link.repository;

import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
Expand All @@ -12,6 +14,19 @@

@Repository
public interface SummaryRepository extends JpaRepository<Summary, Long> {

Optional<Summary> findByLinkIdAndSelectedTrue(Long linkId);

boolean existsByLinkIdAndSelectedTrue(Long linkId);

@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("update Summary s set s.selected = false where s.link.id = :linkId and s.selected = true")
int clearSelectedByLinkId(@Param("linkId") Long linkId);

@Modifying(clearAutomatically = true, flushAutomatically = true)
@Query("update Summary s set s.selected = true where s.id = :summaryId and s.link.id = :linkId")
int selectByIdAndLinkId(@Param("summaryId") Long summaryId, @Param("linkId") Long linkId);

@Query("SELECT s FROM Summary s WHERE s.link IN :links AND s.selected = true")
List<Summary> findAllByLinkInAndSelectedTrue(@Param("links") List<Link> links);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.sofa.linkiving.domain.link.service;

import org.springframework.stereotype.Service;

import com.sofa.linkiving.domain.link.error.LinkErrorCode;
import com.sofa.linkiving.domain.link.repository.SummaryRepository;
import com.sofa.linkiving.global.error.exception.BusinessException;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class SummaryCommandService {

private final SummaryRepository summaryRepository;

/**
* 특정 링크에서 선택된 요약을 변경한다. (링크당 selected=true는 최대 1개)
*/
public void selectSummary(Long linkId, Long summaryId) {
summaryRepository.clearSelectedByLinkId(linkId);
int updated = summaryRepository.selectByIdAndLinkId(summaryId, linkId);
if (updated == 0) {
throw new BusinessException(LinkErrorCode.SUMMARY_NOT_FOUND);
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class SummaryQueryService {
private final SummaryRepository summaryRepository;

public Summary getSummary(Long linkId) {
return summaryRepository.findById(linkId).orElseThrow(
return summaryRepository.findByLinkIdAndSelectedTrue(linkId).orElseThrow(
() -> new BusinessException(LinkErrorCode.SUMMARY_NOT_FOUND)
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,12 @@ public void generateAndSaveSummary(Long linkId) {
log.info("Summary generated for linkId: {}", linkId);

// 3. Summary 엔티티 생성 및 저장
boolean isFirstSummary = !summaryRepository.existsByLinkIdAndSelectedTrue(linkId);
Summary summary = Summary.builder()
.link(link)
.format(Format.CONCISE)
.content(response.summary())
.selected(isFirstSummary)
.build();

summaryRepository.save(summary);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ void shouldGetMessagesWithLinksAndSummaries() {
summaryRepository.save(Summary.builder()
.link(link1)
.content("링크1의 핵심 요약입니다.")
.select(true)
.selected(true)
.build());

Chat chat = chatRepository.save(com.sofa.linkiving.domain.chat.entity.Chat.builder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,17 +55,18 @@ void shouldCreateSummaryWithAllFields() {

Format format = Format.DETAILED;
String content = "This is a detailed summary";
boolean select = true;
boolean selected = true;

Summary summary = Summary.builder()
.link(link)
.format(format)
.content(content)
.select(select)
.selected(selected)
.build();

assertThat(summary.getLink()).isEqualTo(link);
assertThat(summary.getContent()).isEqualTo(content);
assertThat(summary.getFormat()).isEqualTo(format);
assertThat(summary.isSelected()).isTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ void shouldGetLinkSuccessfully() throws Exception {
.link(link)
.content("이것은 요약 내용입니다.")
.format(Format.CONCISE)
.select(true)
.selected(true)
.build());

// when & then
Expand Down Expand Up @@ -335,7 +335,7 @@ void shouldGetLinkListSuccessfully() throws Exception {
.link(link2)
.content("링크 2 요약")
.format(Format.CONCISE)
.select(true)
.selected(true)
.build());

// when & then
Expand Down Expand Up @@ -628,6 +628,7 @@ void shouldRecreateSummarySuccessfully() throws Exception {
summaryRepository.save(Summary.builder()
.link(savedLink)
.content("기존 요약입니다.")
.selected(true)
.build());

String newSummaryText = "새로 생성된 상세 요약입니다.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,15 +123,15 @@ void shouldFindByIdAndMemberWithSummary() {
.link(link)
.content("선택된 요약 내용")
.format(Format.CONCISE)
.select(true)
.selected(true)
.build();
entityManager.persist(selectedSummary);

Summary otherSummary = Summary.builder()
.link(link)
.content("다른 요약")
.format(Format.CONCISE)
.select(false)
.selected(false)
.build();
entityManager.persist(otherSummary);

Expand Down Expand Up @@ -167,7 +167,7 @@ void shouldFindAllByMemberWithSummaryAndCursor() {
.link(link)
.content("요약 " + i)
.format(Format.CONCISE)
.select(true)
.selected(true)
.build();
entityManager.persist(summary);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,18 +59,18 @@ void shouldFindAllByLinkInAndSelectedTrue() {
Summary summary1 = Summary.builder()
.link(link1)
.content("s1")
.select(true)
.selected(true)
.build();
Summary summary2 = Summary.builder()
.link(link2)
.content("s2")
.select(false)
.selected(false)
.build();
Summary summary3 = Summary
.builder()
.link(link3)
.content("s3")
.select(true)
.selected(true)
.build();

em.persist(summary1);
Expand Down Expand Up @@ -109,7 +109,7 @@ void shouldReturnEmptyWhenLinkListIsEmpty() {
Summary summary = Summary.builder()
.link(link)
.content("s1")
.select(true)
.selected(true)
.build();
em.persist(summary);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package com.sofa.linkiving.domain.link.service;

import static org.assertj.core.api.Assertions.*;
import static org.mockito.BDDMockito.*;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;

import com.sofa.linkiving.domain.link.error.LinkErrorCode;
import com.sofa.linkiving.domain.link.repository.SummaryRepository;
import com.sofa.linkiving.global.error.exception.BusinessException;

@ExtendWith(MockitoExtension.class)
@DisplayName("SummaryCommandService 단위 테스트")
public class SummaryCommandServiceTest {

@Mock
private SummaryRepository summaryRepository;

@InjectMocks
private SummaryCommandService summaryCommandService;

@Test
@DisplayName("요약 선택 변경 성공")
void shouldSelectSummarySuccessfully() {
// given
Long linkId = 1L;
Long summaryId = 2L;
given(summaryRepository.clearSelectedByLinkId(linkId)).willReturn(1);
given(summaryRepository.selectByIdAndLinkId(summaryId, linkId)).willReturn(1);

// when
summaryCommandService.selectSummary(linkId, summaryId);

// then
verify(summaryRepository).clearSelectedByLinkId(linkId);
verify(summaryRepository).selectByIdAndLinkId(summaryId, linkId);
}

@Test
@DisplayName("존재하지 않는 요약 선택 시 예외 발생")
void shouldThrowExceptionWhenSummaryNotFound() {
// given
Long linkId = 1L;
Long summaryId = 999L;
given(summaryRepository.clearSelectedByLinkId(linkId)).willReturn(1);
given(summaryRepository.selectByIdAndLinkId(summaryId, linkId)).willReturn(0);

// when & then
assertThatThrownBy(() -> summaryCommandService.selectSummary(linkId, summaryId))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", LinkErrorCode.SUMMARY_NOT_FOUND);

verify(summaryRepository).clearSelectedByLinkId(linkId);
verify(summaryRepository).selectByIdAndLinkId(summaryId, linkId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,30 +36,30 @@ void shouldReturnSummaryWhenSummaryExists() {
// given
Long linkId = 1L;
Summary mockSummary = mock(Summary.class); // Summary 엔티티 Mock
given(summaryRepository.findById(linkId)).willReturn(Optional.of(mockSummary));
given(summaryRepository.findByLinkIdAndSelectedTrue(linkId)).willReturn(Optional.of(mockSummary));

// when
Summary result = summaryQueryService.getSummary(linkId);

// then
assertThat(result).isNotNull();
assertThat(result).isEqualTo(mockSummary);
verify(summaryRepository).findById(linkId);
verify(summaryRepository).findByLinkIdAndSelectedTrue(linkId);
}

@Test
@DisplayName("요약 정보를 찾을 수 없을 때 BusinessException(SUMMARY_NOT_FOUND) 발생")
void shouldThrowBusinessExceptionWhenSummaryNotFound() {
// given
Long linkId = 999L;
given(summaryRepository.findById(linkId)).willReturn(Optional.empty());
given(summaryRepository.findByLinkIdAndSelectedTrue(linkId)).willReturn(Optional.empty());

// when & then
assertThatThrownBy(() -> summaryQueryService.getSummary(linkId))
.isInstanceOf(BusinessException.class)
.hasFieldOrPropertyWithValue("errorCode", LinkErrorCode.SUMMARY_NOT_FOUND);

verify(summaryRepository).findById(linkId);
verify(summaryRepository).findByLinkIdAndSelectedTrue(linkId);
}

@Test
Expand Down