Skip to content

Commit

Permalink
feature: 부스트 위치 변경 및 피드 컨텐츠 추가 (#137)
Browse files Browse the repository at this point in the history
  • Loading branch information
kwanok authored Aug 16, 2024
1 parent e120cfd commit 323126a
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 114 deletions.
Original file line number Diff line number Diff line change
@@ -1,15 +1,11 @@
package com.depromeet.stonebed.domain.feed.api;

import com.depromeet.stonebed.domain.feed.application.FeedService;
import com.depromeet.stonebed.domain.feed.dto.request.FeedBoostRequest;
import com.depromeet.stonebed.domain.feed.dto.request.FeedGetRequest;
import com.depromeet.stonebed.domain.feed.dto.response.FeedGetResponse;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

@Tag(name = "7. [피드]", description = "피드 관련 API입니다.")
Expand All @@ -26,11 +22,4 @@ public FeedGetResponse getFeed(
FeedGetRequest request = new FeedGetRequest(cursor, limit);
return feedService.getFeed(request);
}

@Operation(summary = "부스트 생성", description = "미션 기록에 부스트를 생성하는 API입니다.")
@PostMapping("/boost")
public ResponseEntity<Void> postFeed(final @Valid @RequestBody FeedBoostRequest request) {
feedService.createBoost(request.missionRecordId(), request.count());
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@
import com.depromeet.stonebed.domain.feed.dto.response.FeedContentGetResponse;
import com.depromeet.stonebed.domain.feed.dto.response.FeedGetResponse;
import com.depromeet.stonebed.domain.member.domain.Member;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordBoostRepository;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordRepository;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecordBoost;
import com.depromeet.stonebed.global.error.ErrorCode;
import com.depromeet.stonebed.global.error.exception.CustomException;
import com.depromeet.stonebed.global.util.MemberUtil;
import java.util.List;
import lombok.RequiredArgsConstructor;
Expand All @@ -24,8 +18,6 @@
public class FeedService {
private final FeedRepository feedRepository;
private final MemberUtil memberUtil;
private final MissionRecordRepository missionRecordRepository;
private final MissionRecordBoostRepository missionRecordBoostRepository;

@Transactional(readOnly = true)
public FeedGetResponse getFeed(FeedGetRequest request) {
Expand All @@ -42,23 +34,6 @@ public FeedGetResponse getFeed(FeedGetRequest request) {
return FeedGetResponse.from(feedContentList, nextCursor);
}

public void createBoost(Long missionRecordId, Long boostCount) {
Member currentMember = memberUtil.getCurrentMember();
MissionRecord missionRecord =
missionRecordRepository
.findById(missionRecordId)
.orElseThrow(() -> new CustomException(ErrorCode.MISSION_RECORD_NOT_FOUND));

MissionRecordBoost missionRecordBoost =
MissionRecordBoost.builder()
.missionRecord(missionRecord)
.member(currentMember)
.count(boostCount)
.build();

missionRecordBoostRepository.save(missionRecordBoost);
}

private String getNextCursor(List<FindFeedDto> records, int limit) {
if (records.size() < limit) {
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,16 @@ public record FeedContentGetResponse(
@Schema(description = "미션 기록 이미지 URL", example = "example.jpeg")
String missionRecordImageUrl,
@Schema(description = "미션 기록 생성일") LocalDate createdDate,
@Schema(description = "부스트") Long totalBoostCount) {
@Schema(description = "부스트") Long totalBoostCount,
@Schema(description = "미션 기록 컨텐츠") String content) {
public static FeedContentGetResponse from(FindFeedDto missionRecord) {
return new FeedContentGetResponse(
missionRecord.mission().getId(),
missionRecord.missionRecord().getId(),
missionRecord.author().getId(),
missionRecord.missionRecord().getImageUrl(),
missionRecord.missionRecord().getCreatedAt().toLocalDate(),
missionRecord.totalBoostCount());
missionRecord.totalBoostCount(),
missionRecord.missionRecord().getContent());
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.depromeet.stonebed.domain.missionRecord.api;

import com.depromeet.stonebed.domain.missionRecord.application.MissionRecordService;
import com.depromeet.stonebed.domain.missionRecord.dto.request.MissionRecordBoostRequest;
import com.depromeet.stonebed.domain.missionRecord.dto.request.MissionRecordSaveRequest;
import com.depromeet.stonebed.domain.missionRecord.dto.request.MissionRecordStartRequest;
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarResponse;
Expand All @@ -13,6 +14,7 @@
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

Expand Down Expand Up @@ -77,4 +79,13 @@ public MissionRecordCalendarResponse getMissionRecordsForCalendar(
public MissionRecordCompleteTotal getTotalMissionRecords() {
return missionRecordService.getTotalMissionRecords();
}

@Operation(summary = "부스트 생성", description = "미션 기록에 부스트를 생성한다.")
@PostMapping("/{recordId}/boost")
public ResponseEntity<Void> postFeed(
@PathVariable Long recordId,
final @Valid @RequestBody MissionRecordBoostRequest request) {
missionRecordService.createBoost(recordId, request.count());
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@
import com.depromeet.stonebed.domain.member.domain.Member;
import com.depromeet.stonebed.domain.mission.dao.missionHistory.MissionHistoryRepository;
import com.depromeet.stonebed.domain.mission.domain.MissionHistory;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordBoostRepository;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordRepository;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecordBoost;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecordStatus;
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarDto;
import com.depromeet.stonebed.domain.missionRecord.dto.response.MissionRecordCalendarResponse;
Expand Down Expand Up @@ -33,6 +35,7 @@ public class MissionRecordService {

private final MissionRecordRepository missionRecordRepository;
private final MissionHistoryRepository missionHistoryRepository;
private final MissionRecordBoostRepository missionRecordBoostRepository;
private final MemberUtil memberUtil;

private static final DateTimeFormatter DATE_FORMATTER =
Expand All @@ -59,7 +62,7 @@ public void startMission(Long missionId) {
missionRecordRepository.save(missionRecord);
}

public void saveMission(Long missionId, String text) {
public void saveMission(Long missionId, String content) {
final Member member = memberUtil.getCurrentMember();

MissionHistory missionHistory = findMissionHistoryById(missionId);
Expand All @@ -69,7 +72,7 @@ public void saveMission(Long missionId, String text) {
.findByMemberAndMissionHistory(member, missionHistory)
.orElseThrow(() -> new CustomException(ErrorCode.MISSION_RECORD_NOT_FOUND));

missionRecord.updateText(text);
missionRecord.updateContent(content);
missionRecord.updateStatus(MissionRecordStatus.COMPLETED);

missionRecordRepository.save(missionRecord);
Expand All @@ -84,6 +87,23 @@ public void deleteMissionRecord(Long recordId) {
missionRecordRepository.delete(missionRecord);
}

public void createBoost(Long missionRecordId, Long boostCount) {
Member currentMember = memberUtil.getCurrentMember();
MissionRecord missionRecord =
missionRecordRepository
.findById(missionRecordId)
.orElseThrow(() -> new CustomException(ErrorCode.MISSION_RECORD_NOT_FOUND));

MissionRecordBoost missionRecordBoost =
MissionRecordBoost.builder()
.missionRecord(missionRecord)
.member(currentMember)
.count(boostCount)
.build();

missionRecordBoostRepository.save(missionRecordBoost);
}

private MissionHistory findMissionHistoryById(Long missionId) {
return missionHistoryRepository
.findLatestOneByMissionId(missionId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,30 +43,30 @@ public class MissionRecord extends BaseTimeEntity {
@Column(name = "status", nullable = false)
private MissionRecordStatus status;

@Schema(description = "미션 기록 텍스트", example = "미션 완료 소감")
@Column(name = "text", nullable = true)
private String text;
@Schema(description = "미션 기록 컨텐츠", example = "미션 완료 소감")
@Column(name = "content", nullable = true)
private String content;

@Builder
public MissionRecord(
Member member,
MissionHistory missionHistory,
String imageUrl,
MissionRecordStatus status,
String text) {
String content) {
this.member = member;
this.missionHistory = missionHistory;
this.imageUrl = imageUrl;
this.status = status;
this.text = text;
this.content = content;
}

public void updateImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}

public void updateText(String text) {
this.text = text;
public void updateContent(String content) {
this.content = content;
}

public void updateStatus(MissionRecordStatus status) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
package com.depromeet.stonebed.domain.feed.dto.request;
package com.depromeet.stonebed.domain.missionRecord.dto.request;

import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.NotNull;

public record FeedBoostRequest(
public record MissionRecordBoostRequest(
@NotNull @Min(value = 1) @Max(value = 500) @Schema(description = "부스트 카운트", example = "1")
Long count,
@NotNull @Min(value = 1) @Schema(description = "미션 기록 ID", example = "1")
Long missionRecordId) {}
Long count) {}
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,10 @@
import com.depromeet.stonebed.domain.feed.dto.response.FeedGetResponse;
import com.depromeet.stonebed.domain.member.domain.Member;
import com.depromeet.stonebed.domain.mission.domain.Mission;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordBoostRepository;
import com.depromeet.stonebed.domain.missionRecord.dao.MissionRecordRepository;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecord;
import com.depromeet.stonebed.domain.missionRecord.domain.MissionRecordBoost;
import com.depromeet.stonebed.global.util.MemberUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
Expand All @@ -33,8 +29,6 @@ class FeedServiceTest extends FixtureMonkeySetUp {
@InjectMocks private FeedService feedService;

@Mock private FeedRepository feedRepository;
@Mock private MissionRecordRepository missionRecordRepository;
@Mock private MissionRecordBoostRepository missionRecordBoostRepository;
@Mock private MemberUtil memberUtil;

@Test
Expand Down Expand Up @@ -128,24 +122,4 @@ class FeedServiceTest extends FixtureMonkeySetUp {
verify(feedRepository)
.getFeedContentsUsingCursor(Long.parseLong(cursor), member.getId(), 5);
}

@Test
void 부스트_성공() {
// Given
Member member = fixtureMonkey.giveMeOne(Member.class);
MissionRecord missionRecord = fixtureMonkey.giveMeOne(MissionRecord.class);

when(memberUtil.getCurrentMember()).thenReturn(member);
when(missionRecordRepository.findById(missionRecord.getId()))
.thenReturn(Optional.of(missionRecord));
when(missionRecordBoostRepository.save(any(MissionRecordBoost.class))).thenReturn(null);

// When
feedService.createBoost(missionRecord.getId(), 10L);

// Then
verify(memberUtil).getCurrentMember();
verify(missionRecordRepository).findById(missionRecord.getId());
verify(missionRecordBoostRepository).save(any(MissionRecordBoost.class));
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.depromeet.stonebed.domain.feed.api;
package com.depromeet.stonebed.domain.missionRecord.api;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.depromeet.stonebed.domain.feed.application.FeedService;
import com.depromeet.stonebed.domain.feed.dto.request.FeedBoostRequest;
import com.depromeet.stonebed.domain.missionRecord.application.MissionRecordService;
import com.depromeet.stonebed.domain.missionRecord.dto.request.MissionRecordBoostRequest;
import com.google.gson.Gson;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -20,31 +20,31 @@
import org.springframework.test.web.servlet.MockMvc;

@WebMvcTest(
value = FeedController.class,
value = MissionRecordController.class,
includeFilters = {
@ComponentScan.Filter(
type = FilterType.ASSIGNABLE_TYPE,
classes = AuthenticationEntryPoint.class)
})
@ActiveProfiles("test")
public class FeedControllerTest {
public class MissionRecordControllerTest {
@Autowired private MockMvc mockMvc;

@MockBean private FeedService feedService;
@MockBean private MissionRecordService missionRecordService;

private final Gson gson = new Gson();

@Test
@WithMockUser
void 부스트_성공() throws Exception {
// Given: 요청
FeedBoostRequest feedBoostRequest = new FeedBoostRequest(10L, 1L);
MissionRecordBoostRequest missionRecordBoostRequest = new MissionRecordBoostRequest(10L);

// When & Then: 요청 & 성공
mockMvc.perform(
post("/feed/boost")
post("/records/1/boost")
.contentType(MediaType.APPLICATION_JSON)
.content(gson.toJson(feedBoostRequest))
.content(gson.toJson(missionRecordBoostRequest))
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isCreated())
.andReturn();
Expand All @@ -54,13 +54,13 @@ public class FeedControllerTest {
@WithMockUser
void 부스트_실패_부스트_카운트가_500보다_큰_경우() throws Exception {
// Given: 부스트 카운트가 501인 요청
FeedBoostRequest feedBoostRequest = new FeedBoostRequest(501L, 1L);
MissionRecordBoostRequest missionRecordBoostRequest = new MissionRecordBoostRequest(501L);

// When & Then: 요청 & 응답이 400 Bad Request
mockMvc.perform(
post("/feed/boost")
post("/records/1/boost")
.contentType(MediaType.APPLICATION_JSON)
.content(gson.toJson(feedBoostRequest))
.content(gson.toJson(missionRecordBoostRequest))
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isBadRequest())
.andReturn();
Expand All @@ -70,29 +70,13 @@ public class FeedControllerTest {
@WithMockUser
void 부스트_실패_부스트_카운트가_0인_경우() throws Exception {
// Given: 부스트 카운트가 0인 요청
FeedBoostRequest feedBoostRequest = new FeedBoostRequest(0L, 1L);
MissionRecordBoostRequest missionRecordBoostRequest = new MissionRecordBoostRequest(0L);

// When & Then: 요청 & 응답이 400 Bad Request
mockMvc.perform(
post("/feed/boost")
post("/records/1/boost")
.contentType(MediaType.APPLICATION_JSON)
.content(gson.toJson(feedBoostRequest))
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isBadRequest())
.andReturn();
}

@Test
@WithMockUser
void 부스트_실패_미션기록_고유번호가_1보다_작은_경우() throws Exception {
// Given: 미션 기록 ID가 0인 요청
FeedBoostRequest feedBoostRequest = new FeedBoostRequest(10L, 0L);

// When & Then: 요청 & 응답이 400 Bad Request
mockMvc.perform(
post("/feed/boost")
.contentType(MediaType.APPLICATION_JSON)
.content(gson.toJson(feedBoostRequest))
.content(gson.toJson(missionRecordBoostRequest))
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andExpect(status().isBadRequest())
.andReturn();
Expand Down
Loading

0 comments on commit 323126a

Please sign in to comment.