diff --git a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByPersonGetResponse.java b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByPersonGetResponse.java index fc7b3b0d..7887bd5e 100644 --- a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByPersonGetResponse.java +++ b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByPersonGetResponse.java @@ -1,13 +1,15 @@ package org.layer.domain.answer.controller.dto.response; -import java.util.List; - import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + @Schema(name = "AnswerByPersonGetResponse", description = "개인별 답변 조회 응답 Dto") public record AnswerByPersonGetResponse( @Schema(description = "답변자", example = "홍길동") String name, + @Schema(description = "탈퇴 여부. 탈퇴시 true", example = "false") + Boolean deleted, @Schema(description = "질문-답변 객체", example = "") List answers ) { diff --git a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByQuestionGetResponse.java b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByQuestionGetResponse.java index be6540f8..2df000b9 100644 --- a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByQuestionGetResponse.java +++ b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/AnswerByQuestionGetResponse.java @@ -1,9 +1,9 @@ package org.layer.domain.answer.controller.dto.response; -import java.util.List; - import io.swagger.v3.oas.annotations.media.Schema; +import java.util.List; + @Schema(name = "AnswerByQuestionGetResponse", description = "임시 회고 조회 응답 Dto") public record AnswerByQuestionGetResponse( @Schema(description = "질문 내용", example = "질문 내용입니당") diff --git a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/PersonAndAnswerGetResponse.java b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/PersonAndAnswerGetResponse.java index 7de6a59f..81230146 100644 --- a/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/PersonAndAnswerGetResponse.java +++ b/layer-api/src/main/java/org/layer/domain/answer/controller/dto/response/PersonAndAnswerGetResponse.java @@ -6,6 +6,8 @@ public record PersonAndAnswerGetResponse( @Schema(description = "답변자", example = "홍길동") String name, + @Schema(description = "탈퇴 여부. 탈퇴시 true", example = "false") + Boolean deleted, @Schema(description = "답변 내용", example = "답변 내용입니당") String answerContent ) { diff --git a/layer-api/src/main/java/org/layer/domain/answer/service/AnswerService.java b/layer-api/src/main/java/org/layer/domain/answer/service/AnswerService.java index ce44bcd4..4bf46c12 100644 --- a/layer-api/src/main/java/org/layer/domain/answer/service/AnswerService.java +++ b/layer-api/src/main/java/org/layer/domain/answer/service/AnswerService.java @@ -1,7 +1,7 @@ package org.layer.domain.answer.service; import lombok.RequiredArgsConstructor; - +import lombok.extern.slf4j.Slf4j; import org.layer.domain.analyze.entity.Analyze; import org.layer.domain.analyze.enums.AnalyzeType; import org.layer.domain.analyze.repository.AnalyzeRepository; @@ -40,6 +40,7 @@ import static org.layer.common.exception.AnswerExceptionType.NOT_ANSWERED; import static org.layer.common.exception.MemberSpaceRelationExceptionType.NOT_FOUND_MEMBER_SPACE_RELATION; +@Slf4j @Service @RequiredArgsConstructor @Transactional(readOnly = true) @@ -248,19 +249,19 @@ private List getAnswerByPersonGetResponses(Answers an question.getId(), member.getId()))) .toList(); - return new AnswerByPersonGetResponse(member.getName(), questionAndAnswer); + return new AnswerByPersonGetResponse(member.getName(), member.getDeletedAt() != null, questionAndAnswer); }) .toList(); } private List getAnswerByQuestionGetResponses(Answers answers, Members members, List questions) { + return questions.stream() .map(question -> { List personAndAnswer = answers.getAnswers().stream() .filter(answer -> answer.getQuestionId().equals(question.getId())) - .map(answer -> new PersonAndAnswerGetResponse(members.getName(answer.getMemberId()), - answer.getContent())) + .map(answer -> new PersonAndAnswerGetResponse(members.getName(answer.getMemberId()), members.getDeleted(answer.getMemberId()), answer.getContent())) .toList(); return new AnswerByQuestionGetResponse(question.getContent(), question.getQuestionType().getStyle(), diff --git a/layer-api/src/main/java/org/layer/domain/auth/service/AuthService.java b/layer-api/src/main/java/org/layer/domain/auth/service/AuthService.java index b482b9fd..d88325d9 100644 --- a/layer-api/src/main/java/org/layer/domain/auth/service/AuthService.java +++ b/layer-api/src/main/java/org/layer/domain/auth/service/AuthService.java @@ -93,7 +93,7 @@ public void withdraw(final Long memberId, WithdrawMemberRequest withdrawMemberRe } - // hard delete + // soft delete memberService.withdrawMember(memberId); } diff --git a/layer-api/src/main/java/org/layer/domain/member/service/MemberService.java b/layer-api/src/main/java/org/layer/domain/member/service/MemberService.java index 7369f0b9..64582d95 100644 --- a/layer-api/src/main/java/org/layer/domain/member/service/MemberService.java +++ b/layer-api/src/main/java/org/layer/domain/member/service/MemberService.java @@ -12,14 +12,7 @@ import org.layer.domain.external.google.enums.SheetType; import org.layer.domain.external.google.service.GoogleApiService; import org.layer.domain.jwt.SecurityUtil; -import org.layer.domain.member.controller.dto.CreateFeedbackRequest; -import org.layer.domain.member.controller.dto.GetMemberAnalyzesResponse; -import org.layer.domain.member.controller.dto.GetMemberRecentAnalyzeResponse; -import org.layer.domain.member.controller.dto.GetMemberRecentBadAnalyzeResponse; -import org.layer.domain.member.controller.dto.GetMemberRecentGoodAnalyzeResponse; -import org.layer.domain.member.controller.dto.GetMemberRecentImprovementAnalyzeResponse; -import org.layer.domain.member.controller.dto.UpdateMemberInfoRequest; -import org.layer.domain.member.controller.dto.UpdateMemberInfoResponse; +import org.layer.domain.member.controller.dto.*; import org.layer.domain.member.entity.Member; import org.layer.domain.member.entity.MemberFeedback; import org.layer.domain.member.entity.SocialType; @@ -28,14 +21,12 @@ import org.layer.domain.retrospect.entity.RetrospectStatus; import org.layer.domain.retrospect.repository.RetrospectRepository; import org.layer.domain.space.entity.MemberSpaceRelation; -import org.layer.domain.space.entity.Space; import org.layer.domain.space.repository.MemberSpaceRelationRepository; import org.layer.oauth.dto.service.MemberInfoServiceResponse; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -48,7 +39,7 @@ @RequiredArgsConstructor @Service public class MemberService { -private static final int TWO_MONTHS = 2; + private static final int TWO_MONTHS = 2; private final MemberRepository memberRepository; private final MemberSpaceRelationRepository memberSpaceRelationRepository; @@ -122,7 +113,7 @@ public Member getMemberByMemberId(Long memberId) { @Transactional public void withdrawMember(Long memberId) { Member currentMember = getCurrentMember(); - memberRepository.delete(currentMember); + currentMember.deleteMember(); } @Transactional diff --git a/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java b/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java index 1796ed6b..48ea4912 100644 --- a/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java +++ b/layer-api/src/main/java/org/layer/domain/space/service/SpaceService.java @@ -194,6 +194,7 @@ public List getSpaceMembers(Long memberId, Lo log.info("?"); var SpaceMembers = spaceRepository.findAllSpaceMemberBySpaceIdWithIsLeader(spaceId); return SpaceMembers.stream() + .filter(a -> a.getDeletedAt() == null) .map(SpaceResponse.SpaceMemberResponse::toResponse) .sorted( Comparator.comparing(SpaceResponse.SpaceMemberResponse::isLeader).reversed()) diff --git a/layer-domain/src/main/java/org/layer/domain/member/entity/Member.java b/layer-domain/src/main/java/org/layer/domain/member/entity/Member.java index e9694330..45c6c225 100644 --- a/layer-domain/src/main/java/org/layer/domain/member/entity/Member.java +++ b/layer-domain/src/main/java/org/layer/domain/member/entity/Member.java @@ -8,6 +8,8 @@ import lombok.NoArgsConstructor; import org.layer.domain.common.BaseTimeEntity; +import java.time.LocalDateTime; + @Getter @Entity @NoArgsConstructor(access = AccessLevel.PROTECTED) @@ -36,6 +38,9 @@ public class Member extends BaseTimeEntity { private String profileImageUrl; + private LocalDateTime deletedAt; + + @Builder(access = AccessLevel.PUBLIC) private Member(String name, String email, MemberRole memberRole, SocialType socialType, String socialId) { @@ -53,4 +58,8 @@ public void updateName(String name) { public void updateProfileImageUrl(String profileImageUrl) { this.profileImageUrl = profileImageUrl; } + + public void deleteMember() { + this.deletedAt = LocalDateTime.now(); + } } diff --git a/layer-domain/src/main/java/org/layer/domain/member/entity/Members.java b/layer-domain/src/main/java/org/layer/domain/member/entity/Members.java index 461bcd5c..55316056 100644 --- a/layer-domain/src/main/java/org/layer/domain/member/entity/Members.java +++ b/layer-domain/src/main/java/org/layer/domain/member/entity/Members.java @@ -1,10 +1,10 @@ package org.layer.domain.member.entity; -import java.util.List; - import lombok.Getter; import lombok.RequiredArgsConstructor; +import java.util.List; + @RequiredArgsConstructor @Getter public class Members { @@ -17,4 +17,12 @@ public String getName(Long memberId) { .findAny() .orElse(null); } + + public Boolean getDeleted(Long memberId) { + return members.stream() + .filter(member -> member.getId().equals(memberId)) + .map(m -> m.getDeletedAt() != null) // 지워졌으면 true, 아니면 false + .findAny() + .orElse(null); + } } diff --git a/layer-domain/src/main/java/org/layer/domain/space/dto/SpaceMember.java b/layer-domain/src/main/java/org/layer/domain/space/dto/SpaceMember.java index 7991fc9f..0132ccdb 100644 --- a/layer-domain/src/main/java/org/layer/domain/space/dto/SpaceMember.java +++ b/layer-domain/src/main/java/org/layer/domain/space/dto/SpaceMember.java @@ -3,6 +3,8 @@ import com.querydsl.core.annotations.QueryProjection; import lombok.Getter; +import java.time.LocalDateTime; + @Getter public class SpaceMember { @@ -12,12 +14,14 @@ public class SpaceMember { private final String name; private final Boolean isLeader; + private final LocalDateTime deletedAt; @QueryProjection - public SpaceMember(Long id, String avatar, String name, Boolean isLeader) { + public SpaceMember(Long id, String avatar, String name, Boolean isLeader, LocalDateTime deletedAt) { this.id = id; this.avatar = avatar; this.name = name; this.isLeader = isLeader; + this.deletedAt = deletedAt; } } diff --git a/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepositoryImpl.java b/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepositoryImpl.java index c81897f2..7b78e6a0 100644 --- a/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepositoryImpl.java +++ b/layer-domain/src/main/java/org/layer/domain/space/repository/SpaceRepositoryImpl.java @@ -51,6 +51,7 @@ public Optional findByIdAndJoinedMemberId(Long spaceId, Lo var foundSpace = getSpaceWithMemberCountQuery(memberId) .where(space.id.eq(spaceId)) + .where(member.deletedAt.isNull()) // 삭제되지 않은 회원만 .fetchOne(); if (foundSpace == null || isSpaceWithMemberCountEmpty(foundSpace)) { @@ -63,7 +64,10 @@ public Optional findByIdAndJoinedMemberId(Long spaceId, Lo @Override public Optional findByIdAndJoinedMemberId(Long spaceId) { - var foundSpace = getSpaceWithMemberCountQuery().where(space.id.eq(spaceId)).fetchOne(); + var foundSpace = getSpaceWithMemberCountQuery() + .where(space.id.eq(spaceId)) + .where(member.deletedAt.isNull()) // 삭제되지 않은 회원만 + .fetchOne(); if (foundSpace == null || isSpaceWithMemberCountEmpty(foundSpace)) { return Optional.empty(); @@ -93,7 +97,8 @@ public List findAllSpaceMemberBySpaceIdWithIsLeader(Long spaceId) { member.id, member.profileImageUrl, member.name, - space.leaderId.eq(member.id) + space.leaderId.eq(member.id), + member.deletedAt ) ) .from(memberSpaceRelation) @@ -102,6 +107,7 @@ public List findAllSpaceMemberBySpaceIdWithIsLeader(Long spaceId) { .leftJoin(space) .on(memberSpaceRelation.space.id.eq(space.id)) .where(memberSpaceRelation.space.id.eq(spaceId).and(member.id.isNotNull())) + .where(member.deletedAt.isNull()) // 삭제되지 않은 회원만 .orderBy(memberSpaceRelation.createdAt.asc()) .fetch(); } @@ -128,6 +134,8 @@ private JPAQuery getSpaceWithMemberCountQuery() { .leftJoin(memberCountRelationTable).on(space.id.eq(memberCountRelationTable.space.id)) .leftJoin(member).on(space.leaderId.eq(member.id)) .leftJoin(form).on(space.formId.eq(form.id)) + .leftJoin(member).on(memberSpaceRelation.memberId.eq(member.id)) // memberId와 member의 id 조인 + .where(member.deletedAt.isNull()) // 삭제되지 않은 회원만 .orderBy(space.createdAt.desc()) .orderBy(form.id.desc()) .limit(1); @@ -157,6 +165,8 @@ private JPAQuery getSpaceWithMemberCountQuery(Long memberI .leftJoin(memberCountRelationTable).on(space.id.eq(memberCountRelationTable.space.id)) .leftJoin(member).on(space.leaderId.eq(member.id)) .leftJoin(form).on(space.formId.eq(form.id)) + .leftJoin(member).on(memberSpaceRelation.memberId.eq(member.id)) // memberId와 member의 id 조인 + .where(member.deletedAt.isNull()) // 삭제되지 않은 회원만 .orderBy(space.createdAt.desc()) .orderBy(form.id.desc()) .limit(1);