Skip to content

Commit

Permalink
#15 feat : 아카이브 조회 기능을 추가한다
Browse files Browse the repository at this point in the history
- 조회 엔드포인트를 개발한다
- 카테고리 별로 아카이브를 조회한다
- 단어장 아카이브를 조회한다
  • Loading branch information
packdev937 committed May 13, 2024
1 parent aff069f commit 4c0e745
Show file tree
Hide file tree
Showing 7 changed files with 261 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package kusitms.duduk.apiserver.archive.presentation;

import kusitms.duduk.apiserver.security.infrastructure.CustomUserDetails;
import kusitms.duduk.core.archive.dto.response.ArchiveResponse;
import kusitms.duduk.core.archive.port.input.RetrieveArchiveUseCase;
import kusitms.duduk.domain.global.Category;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
@RequestMapping("/api/archies")
public class ArchiveController implements ArchiveControllerDocs {

private final RetrieveArchiveUseCase retrieveArchiveUseCase;

@GetMapping("/newsletters/{category}")
public ResponseEntity<ArchiveResponse> retrieveArchivedNewsLetters(
@AuthenticationPrincipal final CustomUserDetails customUserDetails,
@PathVariable(name = "category") String category) {

return new ResponseEntity<>(
retrieveArchiveUseCase.retrieveNewsLetters(customUserDetails.getEmail(),
Category.from(category)), HttpStatus.OK);
}

@GetMapping("/terms")
public ResponseEntity<ArchiveResponse> retrieveArchivedTerms(
@AuthenticationPrincipal CustomUserDetails customUserDetails) {
return new ResponseEntity<>(
retrieveArchiveUseCase.retrieveTerms(customUserDetails.getEmail()),
HttpStatus.OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package kusitms.duduk.apiserver.archive.presentation;

import io.swagger.v3.oas.annotations.Operation;
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 kusitms.duduk.apiserver.security.infrastructure.CustomUserDetails;
import kusitms.duduk.common.exception.ErrorResponse;
import kusitms.duduk.core.archive.dto.response.ArchiveResponse;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.PathVariable;

@Tag(name = "Archive", description = "아카이브 API")
public interface ArchiveControllerDocs {

@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "400", description = "BAD REQUEST",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}),
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))})
})
@Operation(summary = "아카이브 뉴스레터 조회", description = "아카이브에 저장되어 있는 뉴스레터를 조회합니다.")
ResponseEntity<ArchiveResponse> retrieveArchivedNewsLetters(
@AuthenticationPrincipal final CustomUserDetails customUserDetails,
@PathVariable final String category
);

@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "OK"),
@ApiResponse(responseCode = "400", description = "BAD REQUEST",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))}),
@ApiResponse(responseCode = "500", description = "INTERNAL SERVER ERROR",
content = {@Content(schema = @Schema(implementation = ErrorResponse.class))})
})
@Operation(summary = "아카이브 단어 조회", description = "아카이브에 저장되어 있는 단어를 조회합니다.")
ResponseEntity<ArchiveResponse> retrieveArchivedTerms(
@AuthenticationPrincipal final CustomUserDetails customUserDetails);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package kusitms.duduk.apiserver.newsletter.presentation;

import io.swagger.v3.oas.annotations.tags.Tag;

@Tag(name = "NewsLetter", description = "뉴스레터 API")
public interface NewsLetterControllerDocs {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package kusitms.duduk.application.archive.service;

import java.util.List;
import kusitms.duduk.common.exception.custom.NotExistsException;
import kusitms.duduk.core.archive.dto.response.ArchiveResponse;
import kusitms.duduk.core.archive.port.input.RetrieveArchiveUseCase;
import kusitms.duduk.core.user.port.output.LoadUserPort;
import kusitms.duduk.domain.global.Category;
import kusitms.duduk.domain.user.User;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Slf4j
@RequiredArgsConstructor
@Service
public class RetrieveArchiveCommand implements RetrieveArchiveUseCase {

private final LoadUserPort loadUserPort;

@Override
public ArchiveResponse retrieveNewsLetters(String email, Category category) {
User user = loadUserPort.findByEmail(email)
.orElseThrow(() -> new NotExistsException("User not found"));

List<Long> newsLetterIds = user.getNewsLettersFromArchive(category);
return new ArchiveResponse(newsLetterIds);
}

@Override
public ArchiveResponse retrieveTerms(String email) {
User user = loadUserPort.findByEmail(email)
.orElseThrow(() -> new NotExistsException("User not found"));

List<Long> termIds = user.getTermsFromArchive();
return new ArchiveResponse(termIds);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package kusitms.duduk.application.archive.service;

import kusitms.duduk.application.newsletter.service.NewsLetterSteps;
import kusitms.duduk.application.term.service.TermSteps;
import kusitms.duduk.core.archive.port.input.RetrieveArchiveUseCase;
import kusitms.duduk.core.newsletter.port.input.ArchiveNewsLetterUseCase;
import kusitms.duduk.core.newsletter.port.output.DeleteNewsLetterPort;
import kusitms.duduk.core.newsletter.port.output.SaveNewsLetterPort;
import kusitms.duduk.core.term.dto.response.ArchiveTermResponse;
import kusitms.duduk.core.term.port.input.ArchiveTermUseCase;
import kusitms.duduk.core.term.port.output.DeleteTermPort;
import kusitms.duduk.core.term.port.output.SaveTermPort;
import kusitms.duduk.domain.newsletter.NewsLetter;
import kusitms.duduk.domain.term.Term;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import kusitms.duduk.application.user.service.UserSteps;
import kusitms.duduk.core.archive.dto.response.ArchiveResponse;
import kusitms.duduk.core.user.port.output.DeleteUserPort;
import kusitms.duduk.core.user.port.output.SaveUserPort;
import kusitms.duduk.domain.global.Category;
import kusitms.duduk.domain.user.User;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.springframework.transaction.annotation.Transactional;

@SpringBootTest
@DisplayName("RetrieveArchiveCommand 테스트")
public class RetrieveArchiveCommandTest {

@Autowired
private SaveUserPort saveUserPort;

@Autowired
private DeleteUserPort deleteUserPort;

@Autowired
private SaveNewsLetterPort saveNewsLetterPort;

@Autowired
private DeleteNewsLetterPort deleteNewsLetterPort;

@Autowired
private SaveTermPort saveTermPort;

@Autowired
private DeleteTermPort deleteTermPort;

@Autowired
private RetrieveArchiveUseCase retrieveArchiveUseCase;

@Autowired
private ArchiveNewsLetterUseCase archiveNewsLetterUseCase;

@Autowired
private ArchiveTermUseCase archiveTermUseCase;

private User savedUser;

@BeforeEach
void setup() {
// 사용자와 뉴스레터, 약관 데이터 생성 및 저장
User user = UserSteps.ROLE_USER_생성_요청();
savedUser = saveUserPort.create(user);
}

@AfterEach
void cleanUp() {
deleteUserPort.deleteAll();
deleteNewsLetterPort.deleteAll();
deleteTermPort.deleteAll();
}

@Test
@Transactional
void 뉴스레터_카테고리별_아카이브를_조회한다() {
// given
// 뉴스레터 생성
NewsLetter newsLetter = NewsLetterSteps.AI_FINANCE_뉴스_레터_생성();
NewsLetter savedNewsLetter = saveNewsLetterPort.create(newsLetter);

String email = savedUser.getEmail().getValue();
Long newsLetterId = savedNewsLetter.getNewsLetterId().getValue();

archiveNewsLetterUseCase.archive(savedUser.getEmail().getValue(),
savedNewsLetter.getNewsLetterId().getValue());

// when
ArchiveResponse newsLettersResponse = retrieveArchiveUseCase.retrieveNewsLetters(email,
Category.FINANCE);

// then
Assertions.assertThat(newsLettersResponse.ids()).contains(newsLetterId);
}

@Test
@Transactional
void 단어_아카이브를_조회한다() {
// given
// 단어 생성
Term term = TermSteps.COMPANY_단어_생성();
Term savedTerm = saveTermPort.save(term);

String email = savedUser.getEmail().getValue();
Long termId = savedTerm.getId().getValue();

archiveTermUseCase.archive(savedUser.getEmail().getValue(),
savedTerm.getId().getValue());

// when
ArchiveResponse response = retrieveArchiveUseCase.retrieveTerms(email);

// then
Assertions.assertThat(response.ids()).contains(termId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package kusitms.duduk.core.archive.dto.response;

import java.util.List;

public record ArchiveResponse(List<Long> ids) {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package kusitms.duduk.core.archive.port.input;

import kusitms.duduk.core.archive.dto.response.ArchiveResponse;
import kusitms.duduk.domain.global.Category;

public interface RetrieveArchiveUseCase {

ArchiveResponse retrieveNewsLetters(String email, Category category);

ArchiveResponse retrieveTerms(String email);
}

0 comments on commit 4c0e745

Please sign in to comment.