Skip to content

Commit

Permalink
feat: 관리자용 요청 주제(토픽) 조회 및 수정 API 구현 (#307) (#320)
Browse files Browse the repository at this point in the history
* feat: 관리자용 토픽 조회 API 구현 (#307)

* feat: 관리자용 요청 주제(토픽) 수정 API 구현 (#307)

* test: static import 추가 (#307)
  • Loading branch information
kdkdhoho authored Oct 27, 2024
1 parent 53b0b08 commit e5e1587
Show file tree
Hide file tree
Showing 10 changed files with 275 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,10 @@ public class Topic extends BaseEntity {

@Column(nullable = false)
private boolean isExposed;

public void update(boolean isExposed, CategoryType categoryType, String title) {
this.isExposed = isExposed;
this.category = categoryType;
this.title = new ListTitle(title);
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.listywave.topic.application.service;

import com.listywave.list.application.domain.category.CategoryType;
import com.listywave.topic.application.domain.Topic;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse;
import com.listywave.topic.application.service.dto.TopicCreateRequest;
import com.listywave.topic.application.service.dto.TopicFindResponse;
import com.listywave.topic.repository.TopicRepository;
import com.listywave.user.application.domain.User;
import com.listywave.user.repository.user.UserRepository;
Expand All @@ -26,8 +28,21 @@ public void create(TopicCreateRequest request, Long userId) {
topicRepository.save(topic);
}

@Transactional(readOnly = true)
public ExposedTopicFindResponse findAllExposed(@Nullable Long cursorId, int size) {
List<Topic> result = topicRepository.findAllExposed(cursorId, size);
return ExposedTopicFindResponse.of(result, size);
}

@Transactional(readOnly = true)
public TopicFindResponse findAll(@Nullable Long cursorId, int size) {
List<Topic> result = topicRepository.findAll(cursorId, size);
long totalCount = (topicRepository.count() / size) + 1;
return TopicFindResponse.from(result, size, totalCount);
}

public void update(Long topicId, boolean isExposed, String categoryCode, String title) {
Topic topic = topicRepository.getById(topicId);
topic.update(isExposed, CategoryType.codeOf(categoryCode), title);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package com.listywave.topic.application.service.dto;

import com.listywave.topic.application.domain.Topic;
import java.time.LocalDateTime;
import java.util.List;
import lombok.Builder;

@Builder
public record TopicFindResponse(
boolean hasNext,
long totalCount,
Long cursorId,
List<TopicDto> topics
) {

public static TopicFindResponse from(List<Topic> topics, int size, long totalCount) {
if (topics.isEmpty()) {
return new TopicFindResponse(false, totalCount, null, List.of());
}

boolean hasNext = false;
if (topics.size() > size) {
hasNext = true;
topics.remove(topics.size() - 1);
}
long cursorId = topics.get(topics.size() - 1).getId();

return TopicFindResponse.builder()
.hasNext(hasNext)
.totalCount(totalCount)
.cursorId(cursorId)
.topics(TopicDto.toList(topics))
.build();
}

@Builder
public record TopicDto(
String categoryEngName,
String categoryKorName,
String title,
String description,
LocalDateTime createdDate,
Long ownerId,
String ownerNickname,
boolean isAnonymous,
boolean isExposed
) {

public static List<TopicDto> toList(List<Topic> topics) {
return topics.stream()
.map(TopicDto::of)
.toList();
}

private static TopicDto of(Topic topic) {
return TopicDto.builder()
.categoryEngName(topic.getCategory().name())
.categoryKorName(topic.getCategory().getViewName())
.title(topic.getTitle().getValue())
.description(topic.getDescription().getValue())
.createdDate(topic.getCreatedDate())
.ownerId(topic.getUser().getId())
.ownerNickname(topic.getUser().getNickname())
.isAnonymous(topic.isAnonymous())
.isExposed(topic.isExposed())
.build();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,14 @@
import com.listywave.topic.application.service.TopicService;
import com.listywave.topic.application.service.dto.ExposedTopicFindResponse;
import com.listywave.topic.application.service.dto.TopicCreateRequest;
import com.listywave.topic.application.service.dto.TopicFindResponse;
import com.listywave.topic.presentation.dto.TopicUpdateRequest;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -32,4 +36,19 @@ ResponseEntity<ExposedTopicFindResponse> findAllExposed(
ExposedTopicFindResponse result = topicService.findAllExposed(cursorId, size);
return ResponseEntity.ok(result);
}

@GetMapping("/admin/topics")
ResponseEntity<TopicFindResponse> findAll(
@RequestParam(required = false) Long cursorId,
@RequestParam(defaultValue = "5") int size
) {
TopicFindResponse result = topicService.findAll(cursorId, size);
return ResponseEntity.ok(result);
}

@PutMapping("/admin/topics/{topicId}")
ResponseEntity<Void> update(@PathVariable Long topicId, @RequestBody TopicUpdateRequest request) {
topicService.update(topicId, request.isExposed(), request.categoryCode(), request.title());
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.listywave.topic.presentation.dto;

public record TopicUpdateRequest(
boolean isExposed,
String categoryCode,
String title
) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@
public interface CustomTopicRepository {

List<Topic> findAllExposed(Long cursorId, int size);

List<Topic> findAll(Long cursorId, int size);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.listywave.topic.application.domain.Topic;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import jakarta.annotation.Nullable;
import java.util.List;
import lombok.RequiredArgsConstructor;

Expand All @@ -15,7 +16,7 @@ public class CustomTopicRepositoryImpl implements CustomTopicRepository {
private final JPAQueryFactory queryFactory;

@Override
public List<Topic> findAllExposed(Long cursorId, int size) {
public List<Topic> findAllExposed(@Nullable Long cursorId, int size) {
return queryFactory
.selectFrom(topic)
.join(user).on(topic.user.id.eq(user.id))
Expand All @@ -28,7 +29,24 @@ public List<Topic> findAllExposed(Long cursorId, int size) {
.fetch();
}

private static BooleanExpression cursorIdLowerThan(Long cursorId) {
private BooleanExpression cursorIdLowerThan(Long cursorId) {
return cursorId == null ? null : topic.id.lt(cursorId);
}

@Override
public List<Topic> findAll(@Nullable Long cursorId, int size) {
return queryFactory
.selectFrom(topic)
.join(user).on(topic.user.id.eq(user.id))
.where(
cursorIdGreaterThan(cursorId)
)
.limit(size + 1)
.orderBy(topic.id.asc())
.fetch();
}

private BooleanExpression cursorIdGreaterThan(Long cursorId) {
return cursorId == null ? null : topic.id.gt(cursorId);
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package com.listywave.topic.repository;

import static com.listywave.common.exception.ErrorCode.RESOURCE_NOT_FOUND;

import com.listywave.common.exception.CustomException;
import com.listywave.topic.application.domain.Topic;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TopicRepository extends JpaRepository<Topic, Long>, CustomTopicRepository {

default Topic getById(Long id) {
return findById(id).orElseThrow(() -> new CustomException(RESOURCE_NOT_FOUND));
}
}
4 changes: 2 additions & 2 deletions src/test/java/com/listywave/common/IntegrationTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.listywave.common;

import static com.listywave.list.fixture.ListFixture.가장_좋아하는_견종_TOP3;
import static com.listywave.user.fixture.UserFixture.동호;
import static com.listywave.user.fixture.UserFixture.서영;
import static com.listywave.user.fixture.UserFixture.유진;
Expand All @@ -15,7 +16,6 @@
import com.listywave.list.application.domain.list.ListEntity;
import com.listywave.list.application.service.CommentService;
import com.listywave.list.application.service.ReplyService;
import com.listywave.list.fixture.ListFixture;
import com.listywave.list.repository.ItemRepository;
import com.listywave.list.repository.comment.CommentRepository;
import com.listywave.list.repository.label.LabelRepository;
Expand Down Expand Up @@ -103,7 +103,7 @@ void setUp() {
js = userRepository.save(정수());
ej = userRepository.save(유진());
sy = userRepository.save(서영());
list = listRepository.save(ListFixture.가장_좋아하는_견종_TOP3(dh, List.of()));
list = listRepository.save(가장_좋아하는_견종_TOP3(dh, List.of()));
log.info("=============================테스트 데이터 셋 생성=============================");
}
}
Loading

0 comments on commit e5e1587

Please sign in to comment.