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

[BE] feature/#250 지도 같이보기 기능 구현 #257

Merged
merged 16 commits into from
Aug 16, 2023
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
11 changes: 11 additions & 0 deletions backend/src/docs/asciidoc/atlas.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
== 모아보기

=== 모아보기에 지도 추가하기

operation::atlas-controller-test/add-topic-to-atlas[snippets='http-request,http-response']

=== 모아보기에서 지도 제거하기

operation::atlas-controller-test/remove-topic-from-atlas[snippets='http-request,http-response']


4 changes: 0 additions & 4 deletions backend/src/docs/asciidoc/bookmark.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,6 @@

operation::bookmark-controller-test/add-topic-in-bookmark[snippets='http-request,http-response']

=== 유저의 토픽 즐겨찾기 목록 조회

operation::bookmark-controller-test/find-topics-in-bookmark[snippets='http-request,http-response']

=== 유저의 토픽 즐겨찾기 단일 삭제
operation::bookmark-controller-test/delete-topic-in-bookmark[snippets='http-request,http-response']

Expand Down
1 change: 1 addition & 0 deletions backend/src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ toc::[]

include::topic.adoc[]
include::pin.adoc[]
include::atlas.adoc[]
include::member.adoc[]
include::permission.adoc[]
include::oauth.adoc[]
Expand Down
8 changes: 4 additions & 4 deletions backend/src/docs/asciidoc/member.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ operation::member-controller-test/find-all-member[snippets='http-request,http-re

operation::member-controller-test/find-member-by-id[snippets='http-request,http-response']

=== 유저가 만든 핀 조회
=== 유저의 모아보기 조회

operation::member-controller-test/find-pins-by-member[snippets='http-request,http-response']
operation::member-controller-test/find-all-topics-in-atlas[snippets='http-request,http-response']

=== 유저가 만든 토픽 조회
=== 유저의 즐겨찾기 조회

operation::member-controller-test/find-topics-by-member[snippets='http-request,http-response']
operation::member-controller-test/find-all-topics-in-bookmark[snippets='http-request,http-response']
4 changes: 4 additions & 0 deletions backend/src/docs/asciidoc/pin.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ operation::pin-controller-test/find-all[snippets='http-request,http-response']

operation::pin-controller-test/find-by-id[snippets='http-request,http-response']

=== 멤버별 핀 목록 조회

operation::pin-controller-test/find-all-pins-by-member-id[snippets='http-request,http-response']

=== 핀 생성

operation::pin-controller-test/add[snippets='http-request,http-response']
Expand Down
4 changes: 4 additions & 0 deletions backend/src/docs/asciidoc/topic.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ operation::topic-controller-test/find-all[snippets='http-request,http-response']

operation::location-controller-test/find-nearby-topics-sorted-by-pin-count[snippets='http-request,http-response']

=== 멤버별 토픽 목록 조회

operation::topic-controller-test/find-all-topics-by-member-id[snippets='http-request,http-response']

=== 토픽 상세 조회

operation::topic-controller-test/find-by-id[snippets='http-request,http-response']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.mapbefine.mapbefine.atlas.application;

import com.mapbefine.mapbefine.atlas.domain.Atlas;
import com.mapbefine.mapbefine.atlas.domain.AtlasRepository;
import com.mapbefine.mapbefine.auth.domain.AuthMember;
import com.mapbefine.mapbefine.member.domain.Member;
import com.mapbefine.mapbefine.member.domain.MemberRepository;
import com.mapbefine.mapbefine.topic.domain.Topic;
import com.mapbefine.mapbefine.topic.domain.TopicRepository;
import java.util.NoSuchElementException;
import java.util.Objects;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Transactional
public class AtlasCommandService {

private final TopicRepository topicRepository;
private final MemberRepository memberRepository;
private final AtlasRepository atlasRepository;

public AtlasCommandService(
TopicRepository topicRepository,
MemberRepository memberRepository,
AtlasRepository atlasRepository
) {
this.topicRepository = topicRepository;
this.memberRepository = memberRepository;
this.atlasRepository = atlasRepository;
}

public void addTopic(AuthMember authMember, Long topicId) {
Long memberId = authMember.getMemberId();

if (Objects.isNull(memberId) || Objects.isNull(topicId)) {
throw new IllegalArgumentException("잘못된 ID가 입력되었습니다.");
}

if (isTopicAlreadyAdded(topicId, memberId)) {
return;
}

Topic topic = findTopicById(topicId);
validateReadPermission(authMember, topic);

Member member = findMemberById(memberId);

Atlas atlas = Atlas.createWithAssociatedMember(topic, member);
atlasRepository.save(atlas);
}

private boolean isTopicAlreadyAdded(Long topicId, Long memberId) {
return atlasRepository.existsByMemberIdAndTopicId(memberId, topicId);
}

private Topic findTopicById(Long topicId) {
return topicRepository.findById(topicId)
.orElseThrow(NoSuchElementException::new);
}

private void validateReadPermission(AuthMember authMember, Topic topic) {
if (authMember.canRead(topic)) {
return;
}
throw new IllegalArgumentException("해당 지도에 접근권한이 없습니다.");
}

private Member findMemberById(Long memberId) {
return memberRepository.findById(memberId)
.orElseThrow(NoSuchElementException::new);
}

public void removeTopic(AuthMember authMember, Long topicId) {
atlasRepository.deleteByMemberIdAndTopicId(authMember.getMemberId(), topicId);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package com.mapbefine.mapbefine.atlas.domain;

import static lombok.AccessLevel.PROTECTED;

import com.mapbefine.mapbefine.member.domain.Member;
import com.mapbefine.mapbefine.topic.domain.Topic;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.util.Objects;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@NoArgsConstructor(access = PROTECTED)
@Getter
public class Atlas {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@ManyToOne
@JoinColumn(name = "topic_id", nullable = false)
private Topic topic;

@ManyToOne
@JoinColumn(name = "member_id", nullable = false)
private Member member;

private Atlas(Topic topic, Member member) {
this.topic = topic;
this.member = member;
}

public static Atlas createWithAssociatedMember(Topic topic, Member member) {
validateNotNull(topic, member);
Atlas atlas = new Atlas(topic, member);

member.addAtlas(atlas);

return atlas;
}

private static void validateNotNull(Topic topic, Member member) {
if (Objects.isNull(topic) || Objects.isNull(member)) {
throw new IllegalArgumentException("지도와 유저는 Null이어선 안됩니다.");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.mapbefine.mapbefine.atlas.domain;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface AtlasRepository extends JpaRepository<Atlas, Long> {

boolean existsByMemberIdAndTopicId(Long memberId, Long topicId);

void deleteByMemberIdAndTopicId(Long memberId, Long topicId);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.mapbefine.mapbefine.atlas.presentation;

import com.mapbefine.mapbefine.atlas.application.AtlasCommandService;
import com.mapbefine.mapbefine.auth.domain.AuthMember;
import com.mapbefine.mapbefine.common.interceptor.LoginRequired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/atlas")
public class AtlasController {

private final AtlasCommandService atlasCommandService;

public AtlasController(AtlasCommandService atlasCommandService) {
this.atlasCommandService = atlasCommandService;
}

@LoginRequired
@PostMapping("/{topicId}")
public ResponseEntity<Void> addTopicToAtlas(AuthMember authMember, @PathVariable Long topicId) {
atlasCommandService.addTopic(authMember, topicId);

return ResponseEntity.status(HttpStatus.CREATED).build();
}
junpakPark marked this conversation as resolved.
Show resolved Hide resolved

@LoginRequired
@DeleteMapping("/{topicId}")
public ResponseEntity<Void> removeTopicFromAtlas(AuthMember authMember, @PathVariable Long topicId) {
atlasCommandService.removeTopic(authMember, topicId);

return ResponseEntity.noContent().build();
}

}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import java.util.Objects;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
Expand All @@ -34,8 +35,8 @@ private Bookmark(Topic topic, Member member) {
this.member = member;
}

// TODO: 2023/08/11 필요한 검증이 무엇이 있을까.. 현재로썬 외부에서 검증하는 방법 밖에 ?
public static Bookmark createWithAssociatedTopicAndMember(Topic topic, Member member) {
validateNotNull(topic, member);
junpakPark marked this conversation as resolved.
Show resolved Hide resolved
Bookmark bookmark = new Bookmark(topic, member);

topic.addBookmark(bookmark);
Expand All @@ -44,4 +45,10 @@ public static Bookmark createWithAssociatedTopicAndMember(Topic topic, Member me
return bookmark;
}

private static void validateNotNull(Topic topic, Member member) {
if (Objects.isNull(topic) || Objects.isNull(member)) {
throw new IllegalArgumentException("지도와 유저는 Null이어선 안됩니다.");
}
}

}
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
package com.mapbefine.mapbefine.bookmark.domain;

import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;

public interface BookmarkRepository extends JpaRepository<Bookmark, Long> {

List<Bookmark> findAllByMemberId(Long memberId);
boolean existsByMemberIdAndTopicId(Long memberId, Long topicId);

void deleteAllByMemberId(Long memberId);

boolean existsByMemberIdAndTopicId(Long memberId, Long topicId);

void deleteByMemberIdAndTopicId(Long memberId, Long topicId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,10 @@

import com.mapbefine.mapbefine.auth.domain.AuthMember;
import com.mapbefine.mapbefine.bookmark.application.BookmarkCommandService;
import com.mapbefine.mapbefine.bookmark.application.BookmarkQueryService;
import com.mapbefine.mapbefine.common.interceptor.LoginRequired;
import com.mapbefine.mapbefine.topic.dto.response.TopicResponse;
import java.net.URI;
import java.util.List;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
Expand All @@ -21,14 +17,8 @@ public class BookmarkController {

private final BookmarkCommandService bookmarkCommandService;

private final BookmarkQueryService bookmarkQueryService;

public BookmarkController(
BookmarkCommandService bookmarkCommandService,
BookmarkQueryService bookmarkQueryService
) {
public BookmarkController(BookmarkCommandService bookmarkCommandService) {
this.bookmarkCommandService = bookmarkCommandService;
this.bookmarkQueryService = bookmarkQueryService;
}

@LoginRequired
Expand All @@ -42,14 +32,6 @@ public ResponseEntity<Void> addTopicInBookmark(
return ResponseEntity.created(URI.create("/bookmarks/" + bookmarkId)).build();
}

@LoginRequired
@GetMapping
public ResponseEntity<List<TopicResponse>> findAllTopicsInBookmark(AuthMember authMember) {
List<TopicResponse> responses = bookmarkQueryService.findAllTopicsInBookmark(authMember);

return ResponseEntity.ok(responses);
}

@LoginRequired
@DeleteMapping
public ResponseEntity<Void> deleteTopicInBookmark(
Expand Down
Loading
Loading