diff --git a/layer-api/src/main/java/org/layer/domain/actionItem/service/ActionItemService.java b/layer-api/src/main/java/org/layer/domain/actionItem/service/ActionItemService.java index 8e8821cc..b04150dd 100644 --- a/layer-api/src/main/java/org/layer/domain/actionItem/service/ActionItemService.java +++ b/layer-api/src/main/java/org/layer/domain/actionItem/service/ActionItemService.java @@ -171,7 +171,8 @@ public SpaceActionItemGetResponse getSpaceRecentActionItems(Long memberId, Long // 종료된 것 중 가장 최근에 만들어진 회고 찾기 Optional recentOpt = retrospectList.stream() .filter(r -> r.getRetrospectStatus().equals(DONE)) // 끝난 회고 찾기 - .sorted((a, b) -> b.getDeadline().compareTo(a.getDeadline())) // deadline 내림차순으로 정렬 + .sorted(Comparator.comparing(Retrospect::getDeadline, + Comparator.nullsLast(Comparator.naturalOrder())).reversed()) // deadline 내림차순, null은 아래로 정렬 .findFirst(); if (recentOpt.isPresent()) { 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..b171bb2a 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) @@ -99,11 +100,14 @@ public void create(AnswerListCreateRequest request, Long spaceId, Long retrospec Answers answers = new Answers(answerRepository.findAllByRetrospectId(retrospectId)); - // 마지막 답변일 경우 -> ai 분석 실행 + // 마지막 답변인 경우 -> ai 분석 실행 if (answers.getWriteCount(retrospectId) == team.getTeamMemberCount()){ - retrospect.updateRetrospectStatus(RetrospectStatus.DONE, time.now()); retrospect.updateAnalysisStatus(AnalysisStatus.PROCEEDING); - retrospectRepository.saveAndFlush(retrospect); + + if(!retrospect.hasDeadLine()){ + retrospect.updateRetrospectStatus(RetrospectStatus.DONE); + } + retrospectRepository.saveAndFlush(retrospect); aiAnalyzeService.createAnalyze(spaceId, retrospectId, answers.getWriteMemberIds()); } @@ -180,11 +184,10 @@ public AnswerListGetResponse getAnalyzeAnswer(Long spaceId, Long retrospectId, L Team team = new Team(memberSpaceRelationRepository.findAllBySpaceId(spaceId)); team.validateTeamMembership(memberId); - Retrospect retrospect = retrospectRepository.findByIdOrThrow(retrospectId); - retrospect.validateRetrospectStatusDone(); - // answer 뽑기 Answers answers = new Answers(answerRepository.findAllByRetrospectId(retrospectId)); + answers.validateIsWriteDone(memberId, retrospectId); + List questionIds = answers.getAnswers().stream().map(Answer::getQuestionId).toList(); List memberIds = answers.getAnswers().stream().map(Answer::getMemberId).toList(); @@ -248,19 +251,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/retrospect/service/RetrospectService.java b/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java index bc9a232e..825943f4 100644 --- a/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java +++ b/layer-api/src/main/java/org/layer/domain/retrospect/service/RetrospectService.java @@ -178,7 +178,11 @@ public void closeRetrospect(Long spaceId, Long retrospectId, Long memberId) { Retrospect retrospect = retrospectRepository.findByIdOrThrow(retrospectId); - retrospect.updateRetrospectStatus(RetrospectStatus.DONE, time.now()); + retrospect.updateRetrospectStatus(RetrospectStatus.DONE); + if (retrospect.getAnalysisStatus().equals(AnalysisStatus.DONE)) { // 이미 분석은 완료했지만, 마감되지 않은 경우 + return; + } + retrospect.updateAnalysisStatus(AnalysisStatus.PROCEEDING); retrospectRepository.saveAndFlush(retrospect); @@ -186,5 +190,6 @@ public void closeRetrospect(Long spaceId, Long retrospectId, Long memberId) { // 회고 ai 분석 시작 aiAnalyzeService.createAnalyze(spaceId, retrospectId, answers.getWriteMemberIds()); + } } 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-api/src/main/resources/application-prod.yml b/layer-api/src/main/resources/application-prod.yml index 0cc8f953..bb726150 100644 --- a/layer-api/src/main/resources/application-prod.yml +++ b/layer-api/src/main/resources/application-prod.yml @@ -3,8 +3,8 @@ spring: import: optional:file:/config/application-secret.properties datasource: url: ${PROD_DB_URL} - username: ${DEV_DB_NAME} - password: ${DEV_DB_PASSWORD} + username: ${PROD_DB_NAME} + password: ${PROD_DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: diff --git a/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java b/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java index 7145cbe0..9280f083 100644 --- a/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java +++ b/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java @@ -43,7 +43,7 @@ public void updateRetrospectStatusToDone() { Map retrospectMap = retrospects.stream() .collect(Collectors.toMap(Retrospect::getId, retrospect -> retrospect)); - retrospects.forEach(retrospect -> retrospect.updateRetrospectStatus(RetrospectStatus.DONE, now)); + retrospects.forEach(retrospect -> retrospect.updateRetrospectStatus(RetrospectStatus.DONE)); retrospectRepository.saveAllAndFlush(retrospects); List retrospectIds = retrospects.stream().map(Retrospect::getId).toList(); diff --git a/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java b/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java index 6507c8fd..1f801ecd 100644 --- a/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java +++ b/layer-domain/src/main/java/org/layer/domain/answer/entity/Answers.java @@ -28,7 +28,6 @@ public class Answers { private final List answers; - public String getAnswerToQuestion(Long questionId, Long memberId) { return answers.stream() .filter(answer -> answer.getQuestionId().equals(questionId) && answer.getMemberId().equals(memberId)) @@ -43,12 +42,20 @@ public boolean hasRetrospectAnswer(Long memberId, Long retrospectId) { .anyMatch(answer -> answer.getMemberId().equals(memberId)); } + public void validateIsWriteDone(Long memberId, Long retrospectId) { + WriteStatus writeStatus = getWriteStatus(memberId, retrospectId); + + if (!writeStatus.equals(WriteStatus.DONE)) { + throw new AnswerException(NOT_ANSWERED); + } + } + public WriteStatus getWriteStatus(Long memberId, Long retrospectId) { boolean isDoneWrite = answers.stream() .filter(answer -> answer.getRetrospectId().equals(retrospectId)) .filter(answer -> answer.getMemberId().equals(memberId)) .anyMatch(answer -> answer.getAnswerStatus().equals(AnswerStatus.DONE)); - if(isDoneWrite){ + if (isDoneWrite) { return WriteStatus.DONE; } @@ -56,7 +63,7 @@ public WriteStatus getWriteStatus(Long memberId, Long retrospectId) { .filter(answer -> answer.getRetrospectId().equals(retrospectId)) .filter(answer -> answer.getMemberId().equals(memberId)) .anyMatch(answer -> answer.getAnswerStatus().equals(AnswerStatus.TEMPORARY)); - if(isTemporaryWrite){ + if (isTemporaryWrite) { return WriteStatus.PROCEEDING; } @@ -70,7 +77,7 @@ public long getWriteCount(Long retrospectId) { Set answerMembers = new HashSet<>(); - if(!answersByRetrospectId.containsKey(retrospectId)){ + if (!answersByRetrospectId.containsKey(retrospectId)) { return 0L; } @@ -111,9 +118,10 @@ public void validateAlreadyAnswer(Long memberId, Long retrospectId) { } } - public String getTotalAnswer(Long rangeQuestionId, Long numberQuestionId){ + public String getTotalAnswer(Long rangeQuestionId, Long numberQuestionId) { Map answerConcatMap = answers.stream() - .filter(answer -> !answer.getQuestionId().equals(rangeQuestionId) && !answer.getQuestionId().equals(numberQuestionId)) + .filter(answer -> !answer.getQuestionId().equals(rangeQuestionId) && !answer.getQuestionId() + .equals(numberQuestionId)) .collect(Collectors.groupingBy( Answer::getMemberId, Collectors.mapping(Answer::getContent, Collectors.joining(" ")))); @@ -125,10 +133,11 @@ public String getTotalAnswer(Long rangeQuestionId, Long numberQuestionId){ return String.join("\n&&\n", answerMap.values()); } - public String getIndividualAnswer(Long rangeQuestionId, Long numberQuestionId, Long memberId){ + public String getIndividualAnswer(Long rangeQuestionId, Long numberQuestionId, Long memberId) { Map answerConcatMap = answers.stream() .filter(answer -> answer.getMemberId().equals(memberId)) - .filter(answer -> !answer.getQuestionId().equals(rangeQuestionId) && !answer.getQuestionId().equals(numberQuestionId)) + .filter(answer -> !answer.getQuestionId().equals(rangeQuestionId) && !answer.getQuestionId() + .equals(numberQuestionId)) .collect(Collectors.groupingBy( Answer::getMemberId, Collectors.mapping(Answer::getContent, Collectors.joining(" ")))); @@ -140,7 +149,6 @@ public String getIndividualAnswer(Long rangeQuestionId, Long numberQuestionId, L return String.join("\n&&\n", answerMap.values()); } - public int getGoalCompletionRate(Long questionId) { int sum = 0; @@ -152,7 +160,7 @@ public int getGoalCompletionRate(Long questionId) { } } - if(count == ZERO){ + if (count == ZERO) { throw new AnswerException(NOT_CONTAIN_ANSWERS); } 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/retrospect/entity/Retrospect.java b/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java index 2f0bcfe0..c4cebf1b 100644 --- a/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java +++ b/layer-domain/src/main/java/org/layer/domain/retrospect/entity/Retrospect.java @@ -87,17 +87,21 @@ public void updateRetrospect(String title, String introduction, LocalDateTime de this.deadline = deadline; } - public void updateRetrospectStatus(RetrospectStatus retrospectStatus, LocalDateTime now) { + public void updateRetrospectStatus(RetrospectStatus retrospectStatus) { isProceedingRetrospect(); - if(this.deadline != null && now.isBefore(this.deadline)){ - return; - } - this.retrospectStatus = retrospectStatus; } public void updateAnalysisStatus(AnalysisStatus analysisStatus) { this.analysisStatus = analysisStatus; } + + public boolean hasDeadLine() { + if (this.deadline == null) { + return false; + } + + return true; + } } 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); diff --git a/layer-external/src/main/java/org/layer/external/ai/service/AIAnalyzeService.java b/layer-external/src/main/java/org/layer/external/ai/service/AIAnalyzeService.java index 965d2391..8097ca64 100644 --- a/layer-external/src/main/java/org/layer/external/ai/service/AIAnalyzeService.java +++ b/layer-external/src/main/java/org/layer/external/ai/service/AIAnalyzeService.java @@ -55,7 +55,6 @@ public void createAnalyze(Long spaceId, Long retrospectId, List memberIds) // 회고 마감 여부 확인 Retrospect retrospect = retrospectRepository.findByIdOrThrow(retrospectId); - retrospect.validateRetrospectStatusDone(); // 답변 조회 Questions questions = new Questions(questionRepository.findAllByRetrospectIdOrderByQuestionOrder(retrospectId)); @@ -67,31 +66,37 @@ public void createAnalyze(Long spaceId, Long retrospectId, List memberIds) String totalAnswer = answers.getTotalAnswer(rangeQuestionId, numberQuestionId); // 분석 요청 - List analyzes = new ArrayList<>(); - - OpenAIResponse aiResponse = openAIService.createAnalyze(totalAnswer); - OpenAIResponse.Content content = aiResponse.parseContent(); - Analyze teamAnalyze = getAnalyzeEntity(retrospectId, answers, rangeQuestionId, numberQuestionId, content, - null, AnalyzeType.TEAM); - analyzes.add(teamAnalyze); - - List individualAnalyzes = memberIds.stream() - .map(memberId -> { - String individualAnswer = answers.getIndividualAnswer(rangeQuestionId, numberQuestionId, memberId); - OpenAIResponse aiIndividualResponse = openAIService.createAnalyze(individualAnswer); - OpenAIResponse.Content individualcontent = aiIndividualResponse.parseContent(); - return getAnalyzeEntity(retrospectId, answers, rangeQuestionId, numberQuestionId, individualcontent, - memberId, AnalyzeType.INDIVIDUAL); - }).toList(); - analyzes.addAll(individualAnalyzes); - - analyzeRepository.saveAll(analyzes); + try{ + List analyzes = new ArrayList<>(); + + OpenAIResponse aiResponse = openAIService.createAnalyze(totalAnswer); + OpenAIResponse.Content content = aiResponse.parseContent(); + + Analyze teamAnalyze = getAnalyzeEntity(retrospectId, answers, rangeQuestionId, numberQuestionId, content, + null, AnalyzeType.TEAM); + analyzes.add(teamAnalyze); + + List individualAnalyzes = memberIds.stream() + .map(memberId -> { + String individualAnswer = answers.getIndividualAnswer(rangeQuestionId, numberQuestionId, memberId); + OpenAIResponse aiIndividualResponse = openAIService.createAnalyze(individualAnswer); + OpenAIResponse.Content individualcontent = aiIndividualResponse.parseContent(); + return getAnalyzeEntity(retrospectId, answers, rangeQuestionId, numberQuestionId, individualcontent, + memberId, AnalyzeType.INDIVIDUAL); + }).toList(); + analyzes.addAll(individualAnalyzes); + + analyzeRepository.saveAll(analyzes); + }catch (Exception e){ + log.info("Not enough Answers"); + } long endTime = System.currentTimeMillis(); // 종료 시간 기록 long duration = endTime - startTime; // 경과 시간 계산 log.info("createAnalyze completed in {} ms", duration); retrospect.updateAnalysisStatus(AnalysisStatus.DONE); + retrospectRepository.save(retrospect); // TODO: 왜 더티체킹이 안될까?? } private Analyze getAnalyzeEntity(Long retrospectId, Answers answers, Long rangeQuestionId, Long numberQuestionId,