Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feat]: survey에 북마크 취소기능 개발 #388

Merged
merged 16 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
8ba484d
feat: survey에 북마크 취소기능을 개발한다
devxb Mar 6, 2024
b9c9e1a
test: 북마크 취소 e2e 테스트의 호스트를 nalab-server로 변경한다
devxb Mar 6, 2024
e5bc334
refactor: 북마크 취소 응답으로 필요없는 필드를 삭제한다
devxb Mar 7, 2024
24e8bf1
refactor: Long타입 응답을 String으로 변경한다
devxb Mar 7, 2024
650a15f
[fix] : gallery 조회 job -> BOOKMARK 및 조회 인자 uppercase로 변경 (#392)
devxb Mar 7, 2024
9bd2b3f
refactor: 북마크 취소 api가 응답 바디를 갖지 않도록 수정한다
devxb Mar 7, 2024
a9bfa86
refactor: setBookmarkedCount를 increase, decrease로 분리한다
devxb Mar 7, 2024
071915a
[refactor] : survey bookmark api가 응답바디를 내려주지 않도록 수정 (#394)
devxb Mar 7, 2024
569ef8e
feat: survey에 북마크 취소기능을 개발한다
devxb Mar 6, 2024
3d52a4d
test: 북마크 취소 e2e 테스트의 호스트를 nalab-server로 변경한다
devxb Mar 6, 2024
08e99fb
refactor: 북마크 취소 응답으로 필요없는 필드를 삭제한다
devxb Mar 7, 2024
2e6872b
refactor: Long타입 응답을 String으로 변경한다
devxb Mar 7, 2024
a4ecfd4
refactor: 북마크 취소 api가 응답 바디를 갖지 않도록 수정한다
devxb Mar 7, 2024
9436f7a
refactor: setBookmarkedCount를 increase, decrease로 분리한다
devxb Mar 7, 2024
d839f00
test: test에서 북마크 검증 필드를 수정한다
devxb Mar 7, 2024
152bfa8
refactor: remove unused import
devxb Mar 7, 2024
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 @@ -29,6 +29,7 @@ public class JwtDecryptInterceptorConfigurer implements WebMvcConfigurer {
"/v1/users",
"/v1/gallerys/previews",
"/v1/surveys/*/bookmarks",
"/v1/surveys/*/bookmarks/cancels",
"/v1/gallerys/logins",
"/v1/gallerys",
};
Expand Down
4 changes: 2 additions & 2 deletions gallery/src/main/kotlin/me/nalab/gallery/domain/Gallery.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class Gallery(

fun getBookmarkedCount(): Int = survey.bookmarkedCount

fun increaseBookmarkedCount() {
survey.bookmarkedCount++
fun setBookmarkedCount(bookmarkedCount: Int) {
survey.bookmarkedCount = bookmarkedCount
dojinyou marked this conversation as resolved.
Show resolved Hide resolved
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ class GalleryService(
}

@Transactional
fun increaseBookmarkCount(targetId: Long) {
galleryRepository.findByTargetIdOrNull(targetId)?.increaseBookmarkedCount()
fun setBookmarkCount(targetId: Long, bookmarkCount: Int) {
galleryRepository.findByTargetIdOrNull(targetId)?.setBookmarkedCount(bookmarkCount)
}

fun getGalleries(job: String, pageable: Pageable): Page<Gallery> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.nalab.gallery.infra

import me.nalab.gallery.domain.GalleryService
import me.nalab.survey.application.common.survey.dto.TargetDto
import me.nalab.survey.application.port.out.persistence.bookmark.SurveyBookmarkListenPort
import org.springframework.dao.OptimisticLockingFailureException
import org.springframework.scheduling.annotation.Async
Expand All @@ -13,14 +14,14 @@ class SurveyBookmarkedListener(
) : SurveyBookmarkListenPort {

@Async
override fun listenBookmarked(targetId: Long) {
override fun listenBookmarked(target: TargetDto) {
runCatching {
galleryService.increaseBookmarkCount(targetId)
galleryService.setBookmarkCount(target.id, target.bookmarkedSurveys.count())
}.recoverCatching {
when (it is OptimisticLockingFailureException) {
true -> {
waitJitter()
listenBookmarked(targetId)
listenBookmarked(target)
}

false -> throw it
Expand Down
124 changes: 124 additions & 0 deletions support/e2e/v1_11_cancel_bookmark_survey.hurl
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
POST http://nalab-server:8080/v1/oauth/default # Default provider를 통해서 로그인 진행
{
"nickname": "cancel_bookmark_survey",
"email": "cancel_bookmark_survey@123456"
}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.access_token" exists
jsonpath "$.token_type" exists

[Captures]
token_type: jsonpath "$.token_type"
auth_token: jsonpath "$.access_token"

##########

POST http://nalab-server:8080/v1/surveys # 발급받은 토큰으로 survey를 생성한다.
Authorization: {{ token_type }} {{ auth_token }}
{
"question_count": 2,
"question": [
{
"type": "choice",
"form_type": "tendency",
"title": "저는 UI, UI, GUI 중에 어떤 분야를 가장 잘하는 것 같나요?",
"choices": [
{
"content": "UI",
"order": 1
},
{
"content": "UX",
"order": 2
},
{
"content": "GUI",
"order": 3
}
],
"max_selectable_count": 1,
"order": 1
},
{
"type": "short",
"form_type": "strength",
"title": "저는 UX, UI, GUI 중에 어떤 분야에 더 강점이 있나요?",
"order": 2
}
]
}

HTTP 201
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.survey_id" exists

[Captures]
survey_id: jsonpath "$.survey_id"

##########

GET http://nalab-server:8080/v1/surveys/{{ survey_id }} # 생성된 survey를 조회한다.

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.survey_id" exists

jsonpath "$.target.id" exists
jsonpath "$.target.nickname" == "cancel_bookmark_survey"

jsonpath "$.question_count" == 2
jsonpath "$.question.[0].question_id" exists
jsonpath "$.question.[0].type" == "choice"
jsonpath "$.question.[0].form_type" == "tendency"
jsonpath "$.question.[0].title" == "저는 UI, UI, GUI 중에 어떤 분야를 가장 잘하는 것 같나요?"
jsonpath "$.question.[0].order" == 1
jsonpath "$.question.[0].max_selectable_count" == 1
jsonpath "$.question.[0].choices.[0].choice_id" exists
jsonpath "$.question.[0].choices.[0].content" == "UI"
jsonpath "$.question.[0].choices.[0].order" == 1
jsonpath "$.question.[0].choices.[1].choice_id" exists
jsonpath "$.question.[0].choices.[1].content" == "UX"
jsonpath "$.question.[0].choices.[1].order" == 2
jsonpath "$.question.[0].choices.[2].choice_id" exists
jsonpath "$.question.[0].choices.[2].content" == "GUI"
jsonpath "$.question.[0].choices.[2].order" == 3
jsonpath "$.question.[1].question_id" exists
jsonpath "$.question.[1].type" == "short"
jsonpath "$.question.[1].form_type" == "strength"
jsonpath "$.question.[1].title" == "저는 UX, UI, GUI 중에 어떤 분야에 더 강점이 있나요?"
jsonpath "$.question.[1].order" == 2

[Captures]
target_id: jsonpath "$.target.id"

##########

POST http://nalab-server:8080/v1/surveys/{{ survey_id }}/bookmarks
Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.target_id" == {{ target_id }}
jsonpath "$.survey_id" == {{ survey_id }}
jsonpath "$.nickname" == "cancel_bookmark_survey"

##########

POST http://nalab-server:8080/v1/surveys/{{ survey_id }}/bookmarks/cancels
Authorization: {{ token_type }} {{ auth_token }}

HTTP 200
[Asserts]
header "Content-type" == "application/json"

jsonpath "$.survey_id" == {{ survey_id }}
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ public interface SurveyBookmarkUseCase {

/**
* targetId에 해당하는 유저에게 survey를 북마크합니다.
* 이미 북마크되어있다면 북마크를 취소합니다.
*/
SurveyBookmarkDto bookmark(Long targetId, Long surveyId);

/**
* targetId에 해당하는 유저에게 survey를 북마크 취소합니다. 북마크 되어있지 않다면, 아무동작도 하지 않습니다.
*/
Long cancelBookmark(Long targetId, Long surveyId);
dojinyou marked this conversation as resolved.
Show resolved Hide resolved

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package me.nalab.survey.application.port.out.persistence.bookmark;

import me.nalab.survey.application.common.survey.dto.TargetDto;

public interface SurveyBookmarkListenPort {

void listenBookmarked(Long targetId);
void listenBookmarked(TargetDto target);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

public interface SurveyBookmarkPort {

void bookmark(Target target);
void updateBookmark(Target target);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import lombok.RequiredArgsConstructor;
import me.nalab.survey.application.common.survey.dto.SurveyBookmarkDto;
import me.nalab.survey.application.common.survey.mapper.TargetDtoMapper;
import me.nalab.survey.application.exception.SurveyDoesNotExistException;
import me.nalab.survey.application.port.in.web.bookmark.SurveyBookmarkUseCase;
import me.nalab.survey.application.port.out.persistence.bookmark.SurveyBookmarkListenPort;
Expand Down Expand Up @@ -30,10 +31,27 @@ public SurveyBookmarkDto bookmark(Long targetId, Long surveyId) {
}

target.bookmark(surveyId);
surveyBookmarkPort.bookmark(target);
surveyBookmarkPort.updateBookmark(target);

surveyBookmarkListener.listenBookmarked(targetId);
surveyBookmarkListener.listenBookmarked(TargetDtoMapper.toTargetDto(target));

return SurveyBookmarkDto.from(surveyId, target);
}

@Override
@Transactional
public Long cancelBookmark(Long targetId, Long surveyId) {
var target = targetFindPort.getTargetById(targetId);

if (!surveyExistCheckPort.isExistSurveyBySurveyId(surveyId)) {
throw new SurveyDoesNotExistException(surveyId);
}

target.cancelBookmark(surveyId);
surveyBookmarkPort.updateBookmark(target);

surveyBookmarkListener.listenBookmarked(TargetDtoMapper.toTargetDto(target));

return surveyId;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.function.LongSupplier;
import lombok.Builder;
Expand Down Expand Up @@ -45,4 +46,11 @@ public void bookmark(Long surveyId) {
var bookmark = new SurveyBookmark(surveyId);
bookmarkedSurveys.add(bookmark);
}

public void cancelBookmark(Long surveyId) {
bookmarkedSurveys.stream()
.filter(surveyBookmark -> Objects.equals(surveyBookmark.surveyId(), surveyId))
.findFirst()
.ifPresent(bookmarkedSurveys::remove);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public class SurveyBookmarkAdaptor implements SurveyBookmarkPort {
private final TargetFindRepository targetFindRepository;

@Override
public void bookmark(Target target) {
public void updateBookmark(Target target) {
var savedTarget = targetFindRepository.findById(target.getId())
.orElseThrow(() -> new TargetDoesNotExistException(target.getId()));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import lombok.RequiredArgsConstructor;
import me.nalab.survey.application.port.in.web.bookmark.SurveyBookmarkUseCase;
import me.nalab.survey.web.adaptor.bookmark.response.SurveyBookmarkResponse;
import me.nalab.survey.web.adaptor.bookmark.response.SurveyBookmarkedResponse;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand All @@ -14,17 +15,25 @@
@RestController
@RequestMapping("/v1")
@RequiredArgsConstructor
public class SurveyBookmarkReplaceController {
public class SurveyBookmarkController {

private final SurveyBookmarkUseCase surveyBookmarkReplaceUseCase;

@ResponseStatus(HttpStatus.OK)
@PostMapping("/surveys/{survey_id}/bookmarks")
public SurveyBookmarkResponse replaceBookmark(@RequestAttribute("logined") Long targetId,
public SurveyBookmarkResponse bookmark(@RequestAttribute("logined") Long targetId,
@PathVariable("survey_id") Long surveyId) {
var surveyBookmarked = surveyBookmarkReplaceUseCase.bookmark(targetId, surveyId);

return SurveyBookmarkResponse.of(surveyBookmarked);
}

@ResponseStatus(HttpStatus.OK)
@PostMapping("/surveys/{survey_id}/bookmarks/cancels")
public SurveyBookmarkedResponse cancelBookmark(@RequestAttribute("logined") Long targetId,
@PathVariable("survey_id") Long surveyId) {
var bookmarkedSurveyId = surveyBookmarkReplaceUseCase.cancelBookmark(targetId, surveyId);

return SurveyBookmarkedResponse.of(bookmarkedSurveyId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package me.nalab.survey.web.adaptor.bookmark.response;

import com.fasterxml.jackson.annotation.JsonProperty;

public record SurveyBookmarkedResponse(
@JsonProperty("survey_id")
String surveyId
) {

public static SurveyBookmarkedResponse of(Long surveyId) {
return new SurveyBookmarkedResponse(surveyId.toString());
}
}
Loading