diff --git a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryFeedback.java b/src/main/java/io/oduck/api/domain/inquiry/dto/AnswerFeedback.java similarity index 65% rename from src/main/java/io/oduck/api/domain/inquiry/dto/InquiryFeedback.java rename to src/main/java/io/oduck/api/domain/inquiry/dto/AnswerFeedback.java index 0ac0848c..30231aab 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryFeedback.java +++ b/src/main/java/io/oduck/api/domain/inquiry/dto/AnswerFeedback.java @@ -7,11 +7,11 @@ @Getter @AllArgsConstructor(access = AccessLevel.PRIVATE) -public class InquiryFeedback { +public class AnswerFeedback { private Long inquiryId; private FeedbackType helpful; - public static InquiryFeedback from(Long inquiryId, FeedbackType helpful) { - return new InquiryFeedback(inquiryId, helpful); + public static AnswerFeedback from(Long inquiryId, FeedbackType helpful) { + return new AnswerFeedback(inquiryId, helpful); } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/dto/CheckAnswerRequest.java b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactId.java similarity index 52% rename from src/main/java/io/oduck/api/domain/inquiry/dto/CheckAnswerRequest.java rename to src/main/java/io/oduck/api/domain/inquiry/dto/ContactId.java index 43fb5aee..8e2e3aa0 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/dto/CheckAnswerRequest.java +++ b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactId.java @@ -6,10 +6,10 @@ @Getter @AllArgsConstructor(access = AccessLevel.PRIVATE) -public class CheckAnswerRequest { - private Long inquiryId; +public class ContactId { + private Long contactId; - public static CheckAnswerRequest from(Long inquiryId) { - return new CheckAnswerRequest(inquiryId); + public static ContactId from(Long inquiryId) { + return new ContactId(inquiryId); } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryReq.java b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactReq.java similarity index 73% rename from src/main/java/io/oduck/api/domain/inquiry/dto/InquiryReq.java rename to src/main/java/io/oduck/api/domain/inquiry/dto/ContactReq.java index 203199f9..60715314 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryReq.java +++ b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactReq.java @@ -6,7 +6,7 @@ import lombok.Getter; import org.hibernate.validator.constraints.Length; -public class InquiryReq { +public class ContactReq { @Getter @AllArgsConstructor public static class PostReq { @@ -25,4 +25,15 @@ public static class PostReq { message = "글자 수는 1~1000를 허용합니다.") private String content; } + + @Getter + @AllArgsConstructor + public static class AnswerReq { + private Long id; + + @NotBlank + @Length(min = 1, max = 1000, + message = "글자 수는 1~1000를 허용합니다.") + private String content; + } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRequestHolder.java b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactRequestHolder.java similarity index 52% rename from src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRequestHolder.java rename to src/main/java/io/oduck/api/domain/inquiry/dto/ContactRequestHolder.java index b27b854b..f86a913b 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRequestHolder.java +++ b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactRequestHolder.java @@ -1,7 +1,7 @@ package io.oduck.api.domain.inquiry.dto; -import io.oduck.api.domain.inquiry.dto.InquiryReq.PostReq; -import io.oduck.api.domain.inquiry.entity.Inquiry; +import io.oduck.api.domain.inquiry.dto.ContactReq.PostReq; +import io.oduck.api.domain.inquiry.entity.Contact; import io.oduck.api.domain.member.entity.Member; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -9,18 +9,17 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) @Getter -public class InquiryRequestHolder { - private Inquiry inquiry; +public class ContactRequestHolder { + private Contact contact; - public static InquiryRequestHolder from(PostReq request, Member member) { - Inquiry inquiry = Inquiry.builder() + public static ContactRequestHolder from(PostReq request, Member member) { + Contact contact = Contact.builder() .title(request.getTitle()) .content(request.getContent()) .type(request.getType()) - .answer(false) - .check(false) + .answered(false) .member(member) .build(); - return new InquiryRequestHolder(inquiry); + return new ContactRequestHolder(contact); } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRes.java b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactRes.java similarity index 76% rename from src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRes.java rename to src/main/java/io/oduck/api/domain/inquiry/dto/ContactRes.java index fac0584d..1b0f6563 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/dto/InquiryRes.java +++ b/src/main/java/io/oduck/api/domain/inquiry/dto/ContactRes.java @@ -1,12 +1,12 @@ package io.oduck.api.domain.inquiry.dto; -import io.oduck.api.domain.inquiry.entity.Inquiry; +import io.oduck.api.domain.inquiry.entity.Contact; import java.time.LocalDate; import java.time.LocalDateTime; import lombok.AllArgsConstructor; import lombok.Getter; -public class InquiryRes { +public class ContactRes { @Getter @AllArgsConstructor @@ -31,8 +31,8 @@ public static class DetailRes { private LocalDate localDate; private boolean answer; - public static DetailRes from(Inquiry inquiry) { - return new DetailRes(inquiry.getTitle(), inquiry.getCreatedAt().toLocalDate(), inquiry.isAnswer()); + public static DetailRes from(Contact contact) { + return new DetailRes(contact.getTitle(), contact.getCreatedAt().toLocalDate(), contact.isAnswered()); } } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/entity/InquiryAnswer.java b/src/main/java/io/oduck/api/domain/inquiry/entity/Answer.java similarity index 70% rename from src/main/java/io/oduck/api/domain/inquiry/entity/InquiryAnswer.java rename to src/main/java/io/oduck/api/domain/inquiry/entity/Answer.java index f51d9133..00105543 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/entity/InquiryAnswer.java +++ b/src/main/java/io/oduck/api/domain/inquiry/entity/Answer.java @@ -5,6 +5,8 @@ import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -15,7 +17,8 @@ @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class InquiryAnswer { +@Table(name = "answer") +public class Answer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -25,6 +28,16 @@ public class InquiryAnswer { private FeedbackType helpful; + @Column(name = "check_answer") + private boolean check = false; + + @OneToOne(mappedBy = "answer") + private Contact contact; + + public void check() { + check = true; + } + public void feedback(FeedbackType helpful) { this.helpful = helpful; } diff --git a/src/main/java/io/oduck/api/domain/inquiry/entity/Inquiry.java b/src/main/java/io/oduck/api/domain/inquiry/entity/Contact.java similarity index 73% rename from src/main/java/io/oduck/api/domain/inquiry/entity/Inquiry.java rename to src/main/java/io/oduck/api/domain/inquiry/entity/Contact.java index 2901f2a5..90201391 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/entity/Inquiry.java +++ b/src/main/java/io/oduck/api/domain/inquiry/entity/Contact.java @@ -2,8 +2,11 @@ import io.oduck.api.domain.member.entity.Member; import io.oduck.api.global.audit.BaseEntity; +import jakarta.persistence.CascadeType; import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; @@ -21,7 +24,7 @@ @NoArgsConstructor(access = lombok.AccessLevel.PROTECTED) @AllArgsConstructor @Builder -public class Inquiry extends BaseEntity { +public class Contact extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; @@ -36,20 +39,16 @@ public class Inquiry extends BaseEntity { @Column(nullable = false, length = 1000) private String content; + @Enumerated(value = EnumType.STRING) private InquiryType type; - private boolean answer = false; - private boolean check = false; + private boolean answered = false; - @OneToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "inquiry_answer_id") - private InquiryAnswer inquiryAnswer; - - public void checkAnswer() { - check = true; - } + @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST) + @JoinColumn(name = "answer_id") + private Answer answer; public void feedback(FeedbackType helpful) { - inquiryAnswer.feedback(helpful); + answer.feedback(helpful); } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepository.java b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepository.java new file mode 100644 index 00000000..90f82e44 --- /dev/null +++ b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepository.java @@ -0,0 +1,13 @@ +package io.oduck.api.domain.inquiry.repository; + +import io.oduck.api.domain.inquiry.entity.Contact; +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; + +public interface ContactRepository extends JpaRepository, ContactRepositoryCustom { + + @Query("select c from Contact c join fetch c.member where c.id = :id") + Optional findWithMemberById(@Param("id") Long id); +} diff --git a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustom.java b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustom.java similarity index 57% rename from src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustom.java rename to src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustom.java index 24d08964..0ce6b07b 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustom.java +++ b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustom.java @@ -1,9 +1,12 @@ package io.oduck.api.domain.inquiry.repository; -import io.oduck.api.domain.inquiry.dto.InquiryRes.MyInquiry; +import io.oduck.api.domain.inquiry.dto.ContactRes.MyInquiry; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -public interface InquiryRepositoryCustom { +public interface ContactRepositoryCustom { + Page getAllByMemberId(Long memberId, Pageable pageable); + + boolean existsByIdAndCheck(Long id, Boolean check); } diff --git a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustomImpl.java b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustomImpl.java similarity index 50% rename from src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustomImpl.java rename to src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustomImpl.java index 8bd3f631..7e3f4fa7 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepositoryCustomImpl.java +++ b/src/main/java/io/oduck/api/domain/inquiry/repository/ContactRepositoryCustomImpl.java @@ -1,12 +1,13 @@ package io.oduck.api.domain.inquiry.repository; -import static io.oduck.api.domain.inquiry.entity.QInquiry.inquiry; +import static io.oduck.api.domain.inquiry.entity.QAnswer.answer; +import static io.oduck.api.domain.inquiry.entity.QContact.contact; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.BooleanExpression; import com.querydsl.jpa.impl.JPAQuery; import com.querydsl.jpa.impl.JPAQueryFactory; -import io.oduck.api.domain.inquiry.dto.InquiryRes.MyInquiry; +import io.oduck.api.domain.inquiry.dto.ContactRes.MyInquiry; import java.util.List; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -18,7 +19,7 @@ @Slf4j @Repository @RequiredArgsConstructor -public class InquiryRepositoryCustomImpl implements InquiryRepositoryCustom { +public class ContactRepositoryCustomImpl implements ContactRepositoryCustom { private final JPAQueryFactory queryFactory; @@ -28,22 +29,42 @@ public Page getAllByMemberId(Long memberId, Pageable pageable) { List content = queryFactory.select( Projections.constructor( MyInquiry.class, - inquiry.id, - inquiry.title, - inquiry.createdAt, - inquiry.answer + contact.id, + contact.title, + contact.createdAt, + contact.answer ) - ).from(inquiry) + ).from(contact) .where(memberIdEq(memberId)) .fetch(); - JPAQuery expression = queryFactory.select(inquiry.id.count()).from(inquiry) + JPAQuery expression = queryFactory.select(contact.id.count()).from(contact) .where(memberIdEq(memberId)); return PageableExecutionUtils.getPage(content, pageable, expression::fetchOne); } + public boolean existsByIdAndCheck(Long id, Boolean check) { + Integer fetchOne = queryFactory.selectOne() + .from(contact) + .join(contact.answer, answer) + .where( + idEq(id), + isCheck(check) + ) + .fetchFirst(); + return fetchOne != null; + } + + private BooleanExpression isCheck(Boolean check) { + return check == null ? null : answer.check.eq(check); + } + + private BooleanExpression idEq(Long id) { + return id == null? null : answer.id.eq(id); + } + private BooleanExpression memberIdEq(Long memberId) { - return memberId == null ? null : inquiry.member.id.eq(memberId); + return memberId == null ? null : contact.member.id.eq(memberId); } } diff --git a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepository.java b/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepository.java deleted file mode 100644 index 2b51bdbe..00000000 --- a/src/main/java/io/oduck/api/domain/inquiry/repository/InquiryRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.oduck.api.domain.inquiry.repository; - -import io.oduck.api.domain.inquiry.entity.Inquiry; -import java.util.Optional; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; -import org.springframework.data.repository.query.Param; - -public interface InquiryRepository extends JpaRepository, InquiryRepositoryCustom { - - @Query("select i from Inquiry i join fetch i.member where i.id = :id") - Optional findWithMemberById(@Param("id") Long id); - - boolean existsByIdAndCheck(Long id, boolean isCheck); -} diff --git a/src/main/java/io/oduck/api/domain/inquiry/service/AnswerHolder.java b/src/main/java/io/oduck/api/domain/inquiry/service/AnswerHolder.java new file mode 100644 index 00000000..e8e5ebb3 --- /dev/null +++ b/src/main/java/io/oduck/api/domain/inquiry/service/AnswerHolder.java @@ -0,0 +1,16 @@ +package io.oduck.api.domain.inquiry.service; + +import io.oduck.api.domain.inquiry.dto.ContactReq.AnswerReq; +import io.oduck.api.domain.inquiry.entity.Contact; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class AnswerHolder { + private Contact contact; + private AnswerReq request; + public static AnswerHolder from(Contact contact, AnswerReq request) { + return new AnswerHolder(contact, request); + } +} diff --git a/src/main/java/io/oduck/api/domain/inquiry/service/ContactPolicy.java b/src/main/java/io/oduck/api/domain/inquiry/service/ContactPolicy.java new file mode 100644 index 00000000..e88ae59f --- /dev/null +++ b/src/main/java/io/oduck/api/domain/inquiry/service/ContactPolicy.java @@ -0,0 +1,21 @@ +package io.oduck.api.domain.inquiry.service; + +import io.oduck.api.domain.inquiry.entity.Contact; +import io.oduck.api.domain.member.entity.Member; +import io.oduck.api.global.exception.ForbiddenException; +import org.springframework.stereotype.Component; + +@Component +public class ContactPolicy { + + public void isAccessOwnInquiry(Contact contact, Member member) { + if(!isOwnInquiry(contact, member)) { + throw new ForbiddenException("not has permission"); + } + contact.getMember().getId(); + } + + private boolean isOwnInquiry(Contact contact, Member member) { + return contact.getMember().getId().equals(member.getId()); + } +} \ No newline at end of file diff --git a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryService.java b/src/main/java/io/oduck/api/domain/inquiry/service/ContactService.java similarity index 66% rename from src/main/java/io/oduck/api/domain/inquiry/service/InquiryService.java rename to src/main/java/io/oduck/api/domain/inquiry/service/ContactService.java index c642614b..5556846e 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryService.java +++ b/src/main/java/io/oduck/api/domain/inquiry/service/ContactService.java @@ -1,12 +1,12 @@ package io.oduck.api.domain.inquiry.service; -import io.oduck.api.domain.inquiry.dto.InquiryReq.PostReq; -import io.oduck.api.domain.inquiry.dto.InquiryRes.DetailRes; -import io.oduck.api.domain.inquiry.dto.InquiryRes.MyInquiry; +import io.oduck.api.domain.inquiry.dto.ContactReq.PostReq; +import io.oduck.api.domain.inquiry.dto.ContactRes.DetailRes; +import io.oduck.api.domain.inquiry.dto.ContactRes.MyInquiry; import io.oduck.api.domain.inquiry.entity.FeedbackType; import io.oduck.api.global.common.PageResponse; -public interface InquiryService { +public interface ContactService { void inquiry(Long memberId, PostReq request); PageResponse getAllByMemberId(Long memberId, int page, int size); @@ -19,7 +19,7 @@ public interface InquiryService { // Page getAll(); // -// void answer(); +// void answer(Long adminId, AnswerReq request); // // void update(Long id); } diff --git a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryServiceImpl.java b/src/main/java/io/oduck/api/domain/inquiry/service/ContactServiceImpl.java similarity index 55% rename from src/main/java/io/oduck/api/domain/inquiry/service/InquiryServiceImpl.java rename to src/main/java/io/oduck/api/domain/inquiry/service/ContactServiceImpl.java index 286fe269..60faff82 100644 --- a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryServiceImpl.java +++ b/src/main/java/io/oduck/api/domain/inquiry/service/ContactServiceImpl.java @@ -1,15 +1,15 @@ package io.oduck.api.domain.inquiry.service; -import static io.oduck.api.domain.inquiry.dto.InquiryReq.PostReq; -import static io.oduck.api.domain.inquiry.dto.InquiryRes.MyInquiry; - -import io.oduck.api.domain.inquiry.dto.CheckAnswerRequest; -import io.oduck.api.domain.inquiry.dto.InquiryFeedback; -import io.oduck.api.domain.inquiry.dto.InquiryRequestHolder; -import io.oduck.api.domain.inquiry.dto.InquiryRes.DetailRes; +import static io.oduck.api.domain.inquiry.dto.ContactReq.PostReq; +import static io.oduck.api.domain.inquiry.dto.ContactRes.MyInquiry; + +import io.oduck.api.domain.inquiry.dto.AnswerFeedback; +import io.oduck.api.domain.inquiry.dto.ContactId; +import io.oduck.api.domain.inquiry.dto.ContactRequestHolder; +import io.oduck.api.domain.inquiry.dto.ContactRes.DetailRes; +import io.oduck.api.domain.inquiry.entity.Contact; import io.oduck.api.domain.inquiry.entity.FeedbackType; -import io.oduck.api.domain.inquiry.entity.Inquiry; -import io.oduck.api.domain.inquiry.repository.InquiryRepository; +import io.oduck.api.domain.inquiry.repository.ContactRepository; import io.oduck.api.domain.member.entity.Member; import io.oduck.api.domain.member.repository.MemberRepository; import io.oduck.api.global.common.PageResponse; @@ -18,82 +18,88 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service +@Transactional(readOnly = true) @RequiredArgsConstructor -public class InquiryServiceImpl implements InquiryService{ +public class ContactServiceImpl implements ContactService { private final MemberRepository memberRepository; - private final InquiryRepository inquiryRepository; + private final ContactRepository contactRepository; - private final InquiryPolicy inquiryPolicy; + private final ContactPolicy contactPolicy; @Override + @Transactional public void inquiry(Long memberId, PostReq request) { Member member = memberRepository.findById(memberId) .orElseThrow(() -> new NotFoundException("member")); - member.inquiry(InquiryRequestHolder.from(request, member)); + member.inquiry(ContactRequestHolder.from(request, member)); } @Override public PageResponse getAllByMemberId(Long memberId, int page, int size) { - Page myInquiries = inquiryRepository.getAllByMemberId(memberId, + Page myInquiries = contactRepository.getAllByMemberId(memberId, PageRequest.of(page, size)); return PageResponse.of(myInquiries); } @Override public DetailRes getByMemberId(Long id, Long memberId) { - Inquiry inquiry = inquiryRepository.findWithMemberById(id) + Contact contact = contactRepository.findWithMemberById(id) .orElseThrow(() -> new NotFoundException("inquiry")); Member member = memberRepository.findById(memberId) .orElseThrow(() -> new NotFoundException("member")); - inquiryPolicy.isAccessOwnInquiry(inquiry, member); + contactPolicy.isAccessOwnInquiry(contact, member); - member.checkAnswer(CheckAnswerRequest.from(inquiry.getId())); - return DetailRes.from(inquiry); + member.checkAnswer(ContactId.from(contact.getId())); + return DetailRes.from(contact); } @Override + @Transactional public boolean hasNotCheckedAnswer(Long id, Long memberId) { - Inquiry inquiry = inquiryRepository.findWithMemberById(id) + Contact contact = contactRepository.findWithMemberById(id) .orElseThrow(() -> new NotFoundException("inquiry")); Member member = memberRepository.findById(memberId) .orElseThrow(() -> new NotFoundException("member")); - inquiryPolicy.isAccessOwnInquiry(inquiry, member); + contactPolicy.isAccessOwnInquiry(contact, member); - return inquiryRepository.existsByIdAndCheck(id, false); + return contactRepository.existsByIdAndCheck(id, false); } @Override + @Transactional public void feedbackAnswer(Long id, Long memberId, FeedbackType helpful) { - Inquiry inquiry = inquiryRepository.findWithMemberById(id) + Contact contact = contactRepository.findWithMemberById(id) .orElseThrow(() -> new NotFoundException("inquiry")); Member member = memberRepository.findById(memberId) .orElseThrow(() -> new NotFoundException("member")); - inquiryPolicy.isAccessOwnInquiry(inquiry, member); + contactPolicy.isAccessOwnInquiry(contact, member); - member.feedbackInquiry(InquiryFeedback.from(id, helpful)); + member.feedbackAnswer(AnswerFeedback.from(id, helpful)); } // @Override // public Page getAll() { // return null; // } -// + // @Override -// public void answer() { -// +// @Transactional +// public void answer(Long adminId, AnswerReq request) { // } -// + // @Override +// @Transactional // public void update(Long id) { // // } diff --git a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryPolicy.java b/src/main/java/io/oduck/api/domain/inquiry/service/InquiryPolicy.java deleted file mode 100644 index 9a63980b..00000000 --- a/src/main/java/io/oduck/api/domain/inquiry/service/InquiryPolicy.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.oduck.api.domain.inquiry.service; - -import io.oduck.api.domain.inquiry.entity.Inquiry; -import io.oduck.api.domain.member.entity.Member; -import io.oduck.api.global.exception.ForbiddenException; -import org.springframework.stereotype.Component; - -@Component -public class InquiryPolicy { - - public void isAccessOwnInquiry(Inquiry inquiry, Member member) { - if(!isOwnInquiry(inquiry, member)) { - throw new ForbiddenException("not has permission"); - } - inquiry.getMember().getId(); - } - - private boolean isOwnInquiry(Inquiry inquiry, Member member) { - return inquiry.getMember().getId().equals(member.getId()); - } -} \ No newline at end of file diff --git a/src/main/java/io/oduck/api/domain/member/entity/Member.java b/src/main/java/io/oduck/api/domain/member/entity/Member.java index b1761551..988716b7 100644 --- a/src/main/java/io/oduck/api/domain/member/entity/Member.java +++ b/src/main/java/io/oduck/api/domain/member/entity/Member.java @@ -2,10 +2,10 @@ import io.oduck.api.domain.attractionPoint.entity.AttractionPoint; import io.oduck.api.domain.bookmark.entity.Bookmark; -import io.oduck.api.domain.inquiry.dto.CheckAnswerRequest; -import io.oduck.api.domain.inquiry.dto.InquiryFeedback; -import io.oduck.api.domain.inquiry.dto.InquiryRequestHolder; -import io.oduck.api.domain.inquiry.entity.Inquiry; +import io.oduck.api.domain.inquiry.dto.AnswerFeedback; +import io.oduck.api.domain.inquiry.dto.ContactId; +import io.oduck.api.domain.inquiry.dto.ContactRequestHolder; +import io.oduck.api.domain.inquiry.entity.Contact; import io.oduck.api.domain.review.entity.ShortReview; import io.oduck.api.domain.reviewLike.entity.ShortReviewLike; import io.oduck.api.domain.starRating.entity.StarRating; @@ -72,7 +72,7 @@ public class Member extends BaseEntity { private List attractionPoints; @OneToMany(mappedBy = "member", cascade = CascadeType.PERSIST) - private List inquiries = new ArrayList<>(); + private List contacts = new ArrayList<>(); @Builder public Member(Long id, Role role, LoginType loginType, AuthSocial authSocial, AuthLocal authLocal, @@ -122,27 +122,27 @@ public void delete() { this.role = Role.WITHDRAWAL; } - public void inquiry(InquiryRequestHolder holder) { - Inquiry inquiry = holder.getInquiry(); + public void inquiry(ContactRequestHolder holder) { + Contact contact = holder.getContact(); - this.inquiries.add(inquiry); + this.contacts.add(contact); } - public void checkAnswer(CheckAnswerRequest request) { - Inquiry inquiry = inquiries.stream() - .filter(i -> i.getId() == request.getInquiryId()) + public void checkAnswer(ContactId request) { + Contact contact = contacts.stream() + .filter(i -> i.getId() == request.getContactId()) .findFirst() .orElseThrow(() -> new NotFoundException("inquiry")); - inquiry.checkAnswer(); + contact.getAnswer().check(); } - public void feedbackInquiry(InquiryFeedback feedback) { - Inquiry inquiry = inquiries.stream() + public void feedbackAnswer(AnswerFeedback feedback) { + Contact contact = contacts.stream() .filter(i -> i.getId() == feedback.getInquiryId()) .findFirst() .orElseThrow(() -> new NotFoundException("inquiry")); - inquiry.feedback(feedback.getHelpful()); + contact.feedback(feedback.getHelpful()); } } diff --git a/src/test/java/io/oduck/api/unit/inquiry/domain/InquiryPolicyTest.java b/src/test/java/io/oduck/api/unit/inquiry/domain/ContactPolicyTest.java similarity index 61% rename from src/test/java/io/oduck/api/unit/inquiry/domain/InquiryPolicyTest.java rename to src/test/java/io/oduck/api/unit/inquiry/domain/ContactPolicyTest.java index 80225779..1e8e6245 100644 --- a/src/test/java/io/oduck/api/unit/inquiry/domain/InquiryPolicyTest.java +++ b/src/test/java/io/oduck/api/unit/inquiry/domain/ContactPolicyTest.java @@ -2,28 +2,28 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; -import io.oduck.api.domain.inquiry.entity.Inquiry; -import io.oduck.api.domain.inquiry.service.InquiryPolicy; +import io.oduck.api.domain.inquiry.entity.Contact; +import io.oduck.api.domain.inquiry.service.ContactPolicy; import io.oduck.api.domain.member.entity.Member; import io.oduck.api.global.exception.ForbiddenException; import org.junit.jupiter.api.Test; -public class InquiryPolicyTest { +public class ContactPolicyTest { - private final InquiryPolicy inquiryPolicy = new InquiryPolicy(); + private final ContactPolicy contactPolicy = new ContactPolicy(); @Test void 질문한_클라이언트와_조회하려는_클라이언트가_다르면_예외가_터진다() { //given Member writer = Member.builder().id(1L).build(); - Inquiry inquiry = Inquiry.builder().member(writer).build(); + Contact contact = Contact.builder().member(writer).build(); Member target = Member.builder().id(2L).build(); //when //then - assertThatThrownBy(() -> inquiryPolicy.isAccessOwnInquiry(inquiry, target)).isInstanceOf( + assertThatThrownBy(() -> contactPolicy.isAccessOwnInquiry(contact, target)).isInstanceOf( ForbiddenException.class); } } diff --git a/src/test/java/io/oduck/api/unit/inquiry/domain/ContactTest.java b/src/test/java/io/oduck/api/unit/inquiry/domain/ContactTest.java new file mode 100644 index 00000000..0c7477ed --- /dev/null +++ b/src/test/java/io/oduck/api/unit/inquiry/domain/ContactTest.java @@ -0,0 +1,91 @@ +package io.oduck.api.unit.inquiry.domain; + + +import static org.assertj.core.api.Assertions.assertThat; + +import io.oduck.api.domain.inquiry.dto.ContactId; +import io.oduck.api.domain.inquiry.dto.AnswerFeedback; +import io.oduck.api.domain.inquiry.dto.ContactReq.PostReq; +import io.oduck.api.domain.inquiry.dto.ContactRequestHolder; +import io.oduck.api.domain.inquiry.entity.Answer; +import io.oduck.api.domain.inquiry.entity.Contact; +import io.oduck.api.domain.inquiry.entity.FeedbackType; +import io.oduck.api.domain.inquiry.entity.InquiryType; +import io.oduck.api.domain.member.entity.Member; +import java.util.ArrayList; +import java.util.List; +import org.junit.jupiter.api.Test; + +public class ContactTest { + + @Test + void 회원은_문의_할_수_있다() { + //given + Member target = Member.builder() + .id(1L) + .contacts(new ArrayList<>()) + .build(); + + PostReq postReq = new PostReq(InquiryType.ADD_REQUEST, "이거 왜 안 됨?", "왜"); + + //when + target.inquiry(ContactRequestHolder.from(postReq, target)); + + //then + assertThat(target.getContacts().size()).isEqualTo(1); + assertThat(target.getContacts().get(0).getTitle()).isEqualTo("이거 왜 안 됨?"); + assertThat(target.getContacts().get(0).getContent()).isEqualTo("왜"); + } + + @Test + void 회원은_운영진의_답변을_확인할_수_있다() { + //given + Member target = Member.builder() + .id(1L) + .contacts(new ArrayList<>()) + .build(); + + Answer answer = Answer.builder() + .check(false) + .build(); + + Contact contact = Contact.builder() + .id(1L) + .answer(answer) + .build(); + + target.getContacts().add(contact); + + //when + target.checkAnswer(ContactId.from(1L)); + + //then + assertThat(contact.getAnswer().isCheck()).isTrue(); + } + + @Test + void 회원은_운영진의_답변에_피드백_할_수_있다() { + //given + Answer answer = Answer.builder() + .helpful(FeedbackType.NOT_SELECT) + .build(); + + Contact contact = Contact.builder() + .answer(answer) + .build(); + + List inquiries = new ArrayList<>(); + inquiries.add(contact); + + Member target = Member.builder() + .id(1L) + .contacts(inquiries) + .build(); + + //when + target.feedbackAnswer(AnswerFeedback.from(null, FeedbackType.HELPFUL)); + + //then + assertThat(target.getContacts().get(0).getAnswer().getHelpful()).isSameAs(FeedbackType.HELPFUL); + } +} diff --git a/src/test/java/io/oduck/api/unit/inquiry/domain/InquiryTest.java b/src/test/java/io/oduck/api/unit/inquiry/domain/InquiryTest.java deleted file mode 100644 index 9c7963ee..00000000 --- a/src/test/java/io/oduck/api/unit/inquiry/domain/InquiryTest.java +++ /dev/null @@ -1,85 +0,0 @@ -package io.oduck.api.unit.inquiry.domain; - - -import static org.assertj.core.api.Assertions.assertThat; - -import io.oduck.api.domain.inquiry.dto.CheckAnswerRequest; -import io.oduck.api.domain.inquiry.dto.InquiryFeedback; -import io.oduck.api.domain.inquiry.dto.InquiryReq.PostReq; -import io.oduck.api.domain.inquiry.dto.InquiryRequestHolder; -import io.oduck.api.domain.inquiry.entity.FeedbackType; -import io.oduck.api.domain.inquiry.entity.Inquiry; -import io.oduck.api.domain.inquiry.entity.InquiryAnswer; -import io.oduck.api.domain.inquiry.entity.InquiryType; -import io.oduck.api.domain.member.entity.Member; -import java.util.ArrayList; -import java.util.List; -import org.junit.jupiter.api.Test; - -public class InquiryTest { - - @Test - void 회원은_문의_할_수_있다() { - //given - Member target = Member.builder() - .id(1L) - .inquiries(new ArrayList<>()) - .build(); - - PostReq postReq = new PostReq(InquiryType.ADD_REQUEST, "이거 왜 안 됨?", "왜"); - - //when - target.inquiry(InquiryRequestHolder.from(postReq, target)); - - //then - assertThat(target.getInquiries().size()).isEqualTo(1); - assertThat(target.getInquiries().get(0).getTitle()).isEqualTo("이거 왜 안 됨?"); - assertThat(target.getInquiries().get(0).getContent()).isEqualTo("왜"); - } - - @Test - void 회원은_운영진의_답변을_확인할_수_있다() { - //given - Member target = Member.builder() - .id(1L) - .inquiries(new ArrayList<>()) - .build(); - - PostReq postReq = new PostReq(InquiryType.ADD_REQUEST, "이거 왜 안 됨?", "왜"); - - target.inquiry(InquiryRequestHolder.from(postReq, target)); - Inquiry inquiry = target.getInquiries().get(0); - - //when - target.checkAnswer(CheckAnswerRequest.from(inquiry.getId())); - - //then - assertThat(inquiry.isCheck()).isTrue(); - } - - @Test - void 회원은_운영진의_답변에_피드백_할_수_있다() { - //given - InquiryAnswer answer = InquiryAnswer.builder() - .helpful(FeedbackType.NOT_SELECT) - .build(); - - Inquiry inquiry = Inquiry.builder() - .inquiryAnswer(answer) - .build(); - - List inquiries = new ArrayList<>(); - inquiries.add(inquiry); - - Member target = Member.builder() - .id(1L) - .inquiries(inquiries) - .build(); - - //when - target.feedbackInquiry(InquiryFeedback.from(null, FeedbackType.HELPFUL)); - - //then - assertThat(target.getInquiries().get(0).getInquiryAnswer().getHelpful()).isSameAs(FeedbackType.HELPFUL); - } -} diff --git a/src/test/java/io/oduck/api/unit/inquiry/repository/InquiryRepositoryTest.java b/src/test/java/io/oduck/api/unit/inquiry/repository/ContactRepositoryTest.java similarity index 54% rename from src/test/java/io/oduck/api/unit/inquiry/repository/InquiryRepositoryTest.java rename to src/test/java/io/oduck/api/unit/inquiry/repository/ContactRepositoryTest.java index 7669cb5a..fd2f3d50 100644 --- a/src/test/java/io/oduck/api/unit/inquiry/repository/InquiryRepositoryTest.java +++ b/src/test/java/io/oduck/api/unit/inquiry/repository/ContactRepositoryTest.java @@ -1,10 +1,11 @@ package io.oduck.api.unit.inquiry.repository; -import static org.assertj.core.api.Assertions.*; +import static org.assertj.core.api.Assertions.assertThat; -import io.oduck.api.domain.inquiry.dto.InquiryReq.PostReq; -import io.oduck.api.domain.inquiry.dto.InquiryRequestHolder; +import io.oduck.api.domain.inquiry.dto.ContactReq.PostReq; +import io.oduck.api.domain.inquiry.dto.ContactRequestHolder; import io.oduck.api.domain.inquiry.entity.InquiryType; +import io.oduck.api.domain.inquiry.repository.ContactRepository; import io.oduck.api.domain.member.entity.Member; import io.oduck.api.domain.member.repository.MemberRepository; import java.util.ArrayList; @@ -18,29 +19,33 @@ @SpringBootTest @TestInstance(Lifecycle.PER_CLASS) @ActiveProfiles("test") -public class InquiryRepositoryTest { +public class ContactRepositoryTest { @Autowired private MemberRepository memberRepository; + @Autowired + private ContactRepository contactRepository; + + @Test void 문의시_문의가_저장된다() { //given Member member = Member.builder() - .inquiries(new ArrayList<>()) + .contacts(new ArrayList<>()) .build(); Member target = memberRepository.save(member); PostReq postReq = new PostReq(InquiryType.ADD_REQUEST, "이거 왜 안 됨?", "왜"); //when - target.inquiry(InquiryRequestHolder.from(postReq, target)); + target.inquiry(ContactRequestHolder.from(postReq, target)); //then - assertThat(target.getInquiries().isEmpty()).isFalse(); - assertThat(target.getInquiries().size()).isEqualTo(1L); - assertThat(target.getInquiries().get(0).getTitle()).isEqualTo("이거 왜 안 됨?"); - assertThat(target.getInquiries().get(0).getContent()).isEqualTo("왜"); - assertThat(target.getInquiries().get(0).getType()).isEqualTo(InquiryType.ADD_REQUEST); + assertThat(target.getContacts().isEmpty()).isFalse(); + assertThat(target.getContacts().size()).isEqualTo(1L); + assertThat(target.getContacts().get(0).getTitle()).isEqualTo("이거 왜 안 됨?"); + assertThat(target.getContacts().get(0).getContent()).isEqualTo("왜"); + assertThat(target.getContacts().get(0).getType()).isEqualTo(InquiryType.ADD_REQUEST); } }