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 @@ -10,4 +10,5 @@ public record CommentListResponse(
String profileImageUrl,
@Schema(description = "댓글 내용", example = "이 옷 정보 알려주세요!") String content,
@Schema(description = "대댓글 존재 여부", example = "false") boolean replied,
@Schema(description = "총 대댓글 개수", example = "0") long replyCount,
@Schema(description = "내가 작성한 댓글인가?", example = "false") boolean isMine) {}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@
import static org.clokey.history.entity.QHistoryImage.historyImage;
import static org.clokey.member.entity.QMember.member;

import com.querydsl.core.Tuple;
import com.querydsl.core.types.Projections;
import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.core.types.dsl.Expressions;
import com.querydsl.core.types.dsl.NumberExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;
import java.util.ArrayList;
import java.util.List;
Expand Down Expand Up @@ -52,6 +54,7 @@ public Slice<CommentListResponse> findAllParentCommentByHistoryId(
member.profileImageUrl,
comment.content,
Expressions.constant(false),
Expressions.constant(0L),
member.id.eq(currentMemberId)))
.from(comment)
.join(comment.member, member)
Expand All @@ -71,9 +74,10 @@ public Slice<CommentListResponse> findAllParentCommentByHistoryId(
results = results.subList(0, size);
}

List<Long> parentIdsWithReplies =
NumberExpression<Long> replyCountExpression = comment.id.count();
List<Tuple> replyCounts =
queryFactory
.select(comment.comment.id)
.select(comment.comment.id, replyCountExpression)
.from(comment)
.where(
comment.comment.id.in(
Expand All @@ -83,9 +87,13 @@ public Slice<CommentListResponse> findAllParentCommentByHistoryId(
.groupBy(comment.comment.id)
.fetch();

// 각 부모 댓글이 대댓글을 가지고 있는지 여부 조회
Map<Long, Boolean> repliedMap =
parentIdsWithReplies.stream().collect(Collectors.toMap(id -> id, id -> true));
// 각 부모 댓글별 대댓글 개수 조회
Map<Long, Long> replyCountMap =
replyCounts.stream()
.collect(
Collectors.toMap(
tuple -> tuple.get(comment.comment.id),
tuple -> tuple.get(replyCountExpression)));

List<CommentListResponse> finalResults =
results.stream()
Expand All @@ -97,7 +105,8 @@ public Slice<CommentListResponse> findAllParentCommentByHistoryId(
c.nickname(),
c.profileImageUrl(),
c.content(),
repliedMap.getOrDefault(c.commentId(), false),
replyCountMap.getOrDefault(c.commentId(), 0L) > 0,
replyCountMap.getOrDefault(c.commentId(), 0L),
c.isMine()))
.toList();

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
package org.clokey.domain.coordinate.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record CoordinateAutoCreateRequest(
@NotBlank(message = "코디의 이름은 비워둘 수 없습니다.")
@Schema(description = "코디의 이름", example = "데이트 코디")
String name,
@Schema(description = "코디의 이름 (비어있으면 날짜 기반으로 자동 생성)", example = "데이트 코디") String name,
@Size(max = 100, message = "메모는 최대 100자까지 입력할 수 있습니다.")
@Schema(description = "코디 메모", example = "내일 이거 입고 나가야 함")
String memo,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.clokey.domain.coordinate.service;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -182,11 +183,21 @@ public CoordinateCreateResponse createCoordinateAuto(CoordinateAutoCreateRequest
validateLookBookOwner(lookBook, currentMember.getId());
validateDailyCoordinate(dailyCoordinate);

dailyCoordinate.addToDailyCoordinateToLookBook(request.name(), request.memo(), lookBook);
String name = request.name();
if (name == null || name.isBlank()) {
name = generateDefaultName(dailyCoordinate.getCreatedAt().toLocalDate());
}

dailyCoordinate.addToDailyCoordinateToLookBook(name, request.memo(), lookBook);

return CoordinateCreateResponse.from(dailyCoordinate);
}

private String generateDefaultName(LocalDate date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.dd.yy");
return "오늘의 코디 (" + date.format(formatter) + ")";
}

@Override
@Transactional
public void updateCoordinate(Long coordinateId, CoordinateUpdateRequest request) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.clokey.domain.comment.controller;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willDoNothing;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
Expand Down Expand Up @@ -292,6 +291,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent1",
false,
0L,
true),
new CommentListResponse(
2L,
Expand All @@ -300,6 +300,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent2",
false,
0L,
true));

given(commentService.getHistoryComments(1L, null, 2, SortDirection.ASC))
Expand Down Expand Up @@ -333,6 +334,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent2",
false,
0L,
true),
new CommentListResponse(
1L,
Expand All @@ -341,6 +343,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent1",
false,
0L,
true));

given(commentService.getHistoryComments(1L, null, 2, SortDirection.DESC))
Expand Down Expand Up @@ -374,6 +377,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent2",
false,
0L,
true));

given(commentService.getHistoryComments(1L, null, 1, SortDirection.ASC))
Expand Down Expand Up @@ -406,6 +410,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent1",
false,
0L,
true),
new CommentListResponse(
2L,
Expand All @@ -414,6 +419,7 @@ class 기록의_댓글_목록_조회_요청_시 {
"testProfile",
"testContent2",
false,
0L,
true));

given(commentService.getHistoryComments(1L, null, 1, SortDirection.ASC))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,10 @@ void setUp() {

// then
assertThat(response.content()).extracting("commentId").containsExactly(1L, 2L, 3L);
assertThat(response.content())
.extracting("commentId", "replied", "replyCount")
.containsExactly(
tuple(1L, true, 1L), tuple(2L, false, 0L), tuple(3L, false, 0L));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -833,14 +833,14 @@ class 코디_자동_생성_요청_시 {
.andExpect(jsonPath("$.result.coordinateId").value(1));
}

@ParameterizedTest
@NullSource
@EmptySource
@ValueSource(strings = {" "})
void 코디의_이름이_null_또는_공백이면_예외가_발생한다(String name) throws Exception {
@Test
void 이름이_비어있어도_정상적으로_생성된다() throws Exception {
// given
CoordinateAutoCreateRequest request =
new CoordinateAutoCreateRequest(name, "testMemo", 1L, 1L);
new CoordinateAutoCreateRequest(null, "testMemo", 1L, 1L);

CoordinateCreateResponse response = new CoordinateCreateResponse(1L);
given(coordinateService.createCoordinateAuto(request)).willReturn(response);

// when & then
ResultActions perform =
Expand All @@ -849,11 +849,11 @@ class 코디_자동_생성_요청_시 {
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(request)));

perform.andExpect(status().isBadRequest())
.andExpect(jsonPath("$.isSuccess").value(false))
.andExpect(jsonPath("$.code").value("COMMON400"))
.andExpect(jsonPath("$.message").value("잘못된 요청입니다."))
.andExpect(jsonPath("$.result.name").value("코디의 이름은 비워둘 수 없습니다."));
perform.andExpect(status().isOk())
.andExpect(jsonPath("$.isSuccess").value(true))
.andExpect(jsonPath("$.code").value("COMMON201"))
.andExpect(jsonPath("$.message").value("요청 성공 및 리소스 생성됨"))
.andExpect(jsonPath("$.result.coordinateId").value(1));
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import static org.assertj.core.api.AssertionsForClassTypes.tuple;
import static org.mockito.BDDMockito.given;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.List;
import org.clokey.IntegrationTest;
import org.clokey.RedisCleaner;
Expand Down Expand Up @@ -753,6 +755,54 @@ void setUp() {
.containsExactly("testName", "testMemo", 1L));
}

@Test
void 이름이_비어있으면_날짜_기반으로_자동_생성한다() {
// given
Coordinate coordinate = coordinateRepository.findById(1L).orElseThrow();
LocalDate createdAt = coordinate.getCreatedAt().toLocalDate();
String expectedName =
"오늘의 코디 (" + createdAt.format(DateTimeFormatter.ofPattern("MM.dd.yy")) + ")";

CoordinateAutoCreateRequest request =
new CoordinateAutoCreateRequest(null, "testMemo", 1L, 1L);

// when
coordinateService.createCoordinateAuto(request);

// then
Coordinate result = coordinateRepository.findById(1L).orElseThrow();

Assertions.assertAll(
() ->
assertThat(result)
.extracting("name", "memo", "lookBook.id")
.containsExactly(expectedName, "testMemo", 1L));
}

@Test
void 이름이_공백이면_날짜_기반으로_자동_생성한다() {
// given
Coordinate coordinate = coordinateRepository.findById(1L).orElseThrow();
LocalDate createdAt = coordinate.getCreatedAt().toLocalDate();
String expectedName =
"오늘의 코디 (" + createdAt.format(DateTimeFormatter.ofPattern("MM.dd.yy")) + ")";

CoordinateAutoCreateRequest request =
new CoordinateAutoCreateRequest(" ", "testMemo", 1L, 1L);

// when
coordinateService.createCoordinateAuto(request);

// then
Coordinate result = coordinateRepository.findById(1L).orElseThrow();

Assertions.assertAll(
() ->
assertThat(result)
.extracting("name", "memo", "lookBook.id")
.containsExactly(expectedName, "testMemo", 1L));
}

@Test
void 나의_코디가_아닌_경우_예외가_발생한다() {
// given
Expand Down