diff --git a/src/docs/asciidoc/MissionBoard-API.adoc b/src/docs/asciidoc/MissionBoard-API.adoc index f63edbd8..95d17782 100644 --- a/src/docs/asciidoc/MissionBoard-API.adoc +++ b/src/docs/asciidoc/MissionBoard-API.adoc @@ -15,12 +15,6 @@ operation::mission-board-controller-test/반복_미션_인증_조회[snipipets=' --- -[[MissionBoard-나의미션인증조회]] -== 나의 미션 인증 조회 -operation::mission-archive-controller-test/나의_미션_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] - ---- - [[MissionBoard-종료된인증조회]] == 종료된 인증 조회 operation::mission-board-controller-test/종료된_인증_조회[snippets='http-request,path-parameters,http-response,response-fields'] diff --git a/src/docs/asciidoc/TeamScore-API.adoc b/src/docs/asciidoc/TeamScore-API.adoc new file mode 100644 index 00000000..12268c8e --- /dev/null +++ b/src/docs/asciidoc/TeamScore-API.adoc @@ -0,0 +1,10 @@ + + +[[TeamScore-API]] += TeamScore API + +[[TeamScore-팀별-불-레벨-경험치-조회]] +=== 팀별_불_레벨_경험치_조회 +operation::team-score-controller-test/팀별_불_레벨_경험치_조회[snippets='http-request,path-parameters,request-fields,http-response,response-fields'] + +--- diff --git a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java index da51ece9..8e90d441 100644 --- a/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/fire/domain/repository/FireCustomRepositoryImpl.java @@ -1,7 +1,6 @@ package com.moing.backend.domain.fire.domain.repository; import com.moing.backend.domain.fire.domain.entity.Fire; -import com.moing.backend.domain.fire.domain.entity.QFire; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; import com.querydsl.jpa.JPAExpressions; diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java index 083474cb..520a41a5 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/req/MissionReq.java @@ -1,7 +1,12 @@ package com.moing.backend.domain.mission.application.dto.req; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; import lombok.*; + @AllArgsConstructor @Builder @NoArgsConstructor diff --git a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java index e7d1ad93..d26f76b2 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java +++ b/src/main/java/com/moing/backend/domain/mission/application/dto/res/SingleMissionBoardRes.java @@ -1,12 +1,15 @@ package com.moing.backend.domain.mission.application.dto.res; +import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.Setter; +import org.checkerframework.checker.units.qual.A; @Getter @Setter @Builder +@AllArgsConstructor public class SingleMissionBoardRes { private Long missionId; private String dueTo; // 날짜 diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java new file mode 100644 index 00000000..824407a3 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionCheckScheduler.java @@ -0,0 +1,4 @@ +package com.moing.backend.domain.mission.application.service; + +public class MissionCheckScheduler { +} diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java new file mode 100644 index 00000000..18866d60 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/application/service/MissionTerminationUseCase.java @@ -0,0 +1,47 @@ +package com.moing.backend.domain.mission.application.service; + +import com.moing.backend.domain.member.domain.service.MemberGetService; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Service +@Transactional +@RequiredArgsConstructor +public class MissionTerminationUseCase { + + private final MemberGetService memberGetService; + private final MissionQueryService missionQueryService; + + // 스케쥴러에서 호출 + public void terminateMission() { + + List missionByDueTo = missionQueryService.findMissionByDueTo(); + + missionByDueTo.stream().forEach( + // 미션 종료 처리 + mission -> mission.updateStatus(MissionStatus.END) + + ); + } + + // 미션 점수 반영 -> MissionState + + + // MissionState 조회 해서 미션 점수 현황조회 + + public void getMissionScoreStatus() { + + } + + // 팀별 점수 반영 + public void updateMissionScore() { + + } + +} diff --git a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java index 39aece59..66177310 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/entity/Mission.java @@ -81,7 +81,7 @@ public void setTeam(Team team) { this.team = team; } - public void setStatus(MissionStatus missionStatus) { + public void updateStatus(MissionStatus missionStatus) { this.status = missionStatus; } } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java index 7cf2b174..61867e4e 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepository.java @@ -18,4 +18,7 @@ public interface MissionCustomRepository { Optional> findRepeatMissionByMemberId(Long memberId, Listteams); + Optional> findMissionByDueTo(); + + } \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java index 5cb5a266..b9e1ec6c 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/repository/MissionCustomRepositoryImpl.java @@ -10,6 +10,7 @@ import javax.persistence.EntityManager; +import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @@ -59,6 +60,18 @@ public Optional> findRepeatMissionByMemberId(Long m .fetch()); } + + @Override + public Optional> findMissionByDueTo() { + + LocalDateTime oneHourAgo = LocalDateTime.now().minusHours(1); + + return Optional.ofNullable(queryFactory + .selectFrom(mission) + .where( + mission.dueTo.after(oneHourAgo) + ).fetch()); + } @Override public Optional> findSingleMissionByMemberId(Long memberId, List teams) { return Optional.ofNullable(queryFactory @@ -75,8 +88,7 @@ public Optional> findSingleMissionByMemberId(Long m mission.type.eq(MissionType.ONCE) ) - .fetch() - - ); + .fetch()); } + } diff --git a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java index 2bd9070b..4d4045d4 100644 --- a/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java +++ b/src/main/java/com/moing/backend/domain/mission/domain/service/MissionQueryService.java @@ -5,6 +5,7 @@ import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.domain.entity.Mission; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.exception.NotFoundEndMissionException; import com.moing.backend.domain.mission.exception.NotFoundMissionException; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.team.application.dto.response.GetTeamResponse; @@ -41,4 +42,12 @@ public List findAllSingleMission(Long memberId) { List teams = teamGetService.getTeamIdByMemberId(memberId); return missionRepository.findSingleMissionByMemberId(memberId, teams).orElseThrow(NotFoundMissionException::new); } + + /** + * 스케쥴러에서 한시간 단위로 실행 + * 현재 시간으로부터 1시간 이내 종료 되는 미션 리턴 + */ + public List findMissionByDueTo() { + return missionRepository.findMissionByDueTo().orElseThrow(NotFoundEndMissionException::new); + } } diff --git a/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java new file mode 100644 index 00000000..942f2861 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/mission/exception/NotFoundEndMissionException.java @@ -0,0 +1,12 @@ +package com.moing.backend.domain.mission.exception; + +import com.moing.backend.global.response.ErrorCode; +import org.springframework.http.HttpStatus; + +public class NotFoundEndMissionException extends MissionException { + + public NotFoundEndMissionException() { + super(ErrorCode.NOT_FOUND_MISSION, + HttpStatus.NOT_FOUND); + } +} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java index 972479bb..e0c82411 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/dto/req/MissionArchiveReq.java @@ -2,7 +2,6 @@ import lombok.*; -@AllArgsConstructor @Builder @NoArgsConstructor @Getter @@ -10,4 +9,10 @@ public class MissionArchiveReq { private String status; private String archive; //사진일 경우 파일명, 이외에는 text,link + + @Builder + public MissionArchiveReq(String status, String archive) { + this.status = status; + this.archive = archive; + } } diff --git a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java similarity index 90% rename from src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java rename to src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java index 6b0a4c82..2a4d71ef 100644 --- a/src/main/java/com/moing/backend/domain/mission/application/service/MissionArchiveBoardUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveBoardUseCase.java @@ -1,4 +1,4 @@ -package com.moing.backend.domain.mission.application.service; +package com.moing.backend.domain.missionArchive.application.service; import com.moing.backend.domain.member.domain.entity.Member; import com.moing.backend.domain.member.domain.service.MemberGetService; @@ -45,8 +45,7 @@ public List getActiveSingleMissions(Long teamId, String m Member member = memberGetService.getMemberBySocialId(memberId); - List mySingleMissionArchives = missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); - return MissionArchiveMapper.mapToSingleMissionBoardResList(mySingleMissionArchives); + return missionArchiveQueryService.findMySingleMissionArchives(member.getMemberId(), teamId, MissionStatus.ONGOING); } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java index d42a98c2..79ad517c 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveCreateUseCase.java @@ -10,12 +10,16 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -28,37 +32,38 @@ public class MissionArchiveCreateUseCase { private final MissionArchiveSaveService missionArchiveSaveService; private final MissionArchiveQueryService missionArchiveQueryService; private final MissionArchiveDeleteService missionArchiveDeleteService; + private final MissionHeartQueryService missionHeartQueryService; private final MissionQueryService missionQueryService; - private final MemberGetService memberGetService; - private final MissionArchiveScoreService missionArchiveScoreService; + private final MissionStateSaveService missionStateSaveService; + private final MissionStateUseCase missionStateUseCase; + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; - // 미션 인증 public MissionArchiveRes createArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); - Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); MissionArchive newArchive = MissionArchiveMapper.mapToMissionArchive(missionReq, member, mission); + // 인증 완료한 미션인지 확인 if (isDoneMission(memberId,mission)) { throw new NoMoreMissionArchiveException(); } - - // archive 회차 - if (mission.getType().equals(MissionType.ONCE)) { - newArchive.updateCount(1L); - } - else { + // 반복 미션일 경우 + if (mission.getType() == MissionType.REPEAT) { newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)+1); + }else { + newArchive.updateCount(missionArchiveQueryService.findMyDoneArchives(memberId, missionId)); } + missionStateUseCase.updateMissionState(member, mission, newArchive); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(newArchive),memberId); } @@ -68,18 +73,7 @@ public Boolean isDoneMission(Long memberId,Mission mission) { return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); } - // 이 미션을 완료 했는지 - public Boolean isEndMission(Member member,Mission mission) { - Team team = mission.getTeam(); - - Long missionsCountByTeam = missionQueryService.findMissionsCountByTeam(team.getTeamId()); - if (missionsCountByTeam == team.getNumOfMember()-1) { - mission.setStatus(MissionStatus.END); - return true; - } - return false; - } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java deleted file mode 100644 index 89d12f78..00000000 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveScoreService.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.moing.backend.domain.missionArchive.application.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.service.ScoreQueryService; -import com.moing.backend.domain.score.domain.service.ScoreSaveService; -import com.moing.backend.domain.team.domain.entity.Team; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class MissionArchiveScoreService { - - private final ScoreQueryService scoreQueryService; - - public void addScore(Team team) { - // steps - // 단계별 - Score score = scoreQueryService.findByTeamId(team.getTeamId()); - score.updateScore(20); - - } - -} diff --git a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java index 4e7b956a..f9b19412 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/application/service/MissionArchiveUpdateUseCase.java @@ -12,9 +12,14 @@ import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; import com.moing.backend.domain.missionArchive.application.mapper.MissionArchiveMapper; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveDeleteService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveQueryService; import com.moing.backend.domain.missionArchive.domain.service.MissionArchiveSaveService; +import com.moing.backend.domain.missionArchive.exception.NoMoreMissionArchiveException; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; import com.moing.backend.domain.missionHeart.domain.entity.MissionHeart; import com.moing.backend.domain.missionHeart.domain.service.MissionHeartQueryService; import com.moing.backend.domain.team.domain.entity.Team; @@ -40,13 +45,15 @@ public class MissionArchiveUpdateUseCase { private final IssuePresignedUrlUseCase getPresignedUrlUseCase; + private final MissionStateSaveService missionStateSaveService; + private final MissionStateUseCase missionStateUseCase; + // 미션 재인증 (수정하기도 포함됨) public MissionArchiveRes updateArchive(String userSocialId, Long missionId, MissionArchiveReq missionReq) { Member member = memberGetService.getMemberBySocialId(userSocialId); Long memberId = member.getMemberId(); - Mission mission = missionQueryService.findMissionById(missionId); Team team = mission.getTeam(); @@ -54,15 +61,20 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss if (mission.getWay() == MissionWay.PHOTO && missionArchiveQueryService.isDone(memberId, missionId)) { //s3삭제 + } MissionArchive updateArchive = missionArchiveQueryService.findMyArchive(memberId, missionId).get(0); + // 단일 미션 && 미션 종료 직전인지 확인 + if (mission.getType() == MissionType.ONCE && missionStateUseCase.isAbleToEnd(missionId)) { + mission.updateStatus(MissionStatus.SUCCESS); + // 점수 반영 로직 + + } + + if (mission.getType().equals(MissionType.ONCE)) { - // missionArchive 2개 이상일 때 예외처리 필요 -// if (isDoneSingleMission(mission)) { -// missionArchiveScoreService.addScore(team); -// } updateArchive.updateCount(1L); } else{ @@ -70,11 +82,16 @@ public MissionArchiveRes updateArchive(String userSocialId, Long missionId, Miss } updateArchive.updateArchive(missionReq); + missionStateSaveService.saveMissionState(member,mission, updateArchive.getStatus()); return MissionArchiveMapper.mapToMissionArchiveRes(missionArchiveSaveService.save(updateArchive),memberId); } + // 이 미션을 완료 했는지 + public Boolean isDoneMission(Long memberId,Mission mission) { + return missionArchiveQueryService.findMyDoneArchives(memberId, mission.getId()) >= mission.getNumber(); + } } diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java index fe6014d9..b6fec1f3 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepository.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; @@ -12,7 +13,8 @@ import java.util.Optional; @Repository public interface MissionArchiveCustomRepository { - Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, MissionArchiveStatus archiveStatus, OrderCondition orderCondition); + Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); + Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status,OrderCondition orderCondition); Optional> findMyArchives(Long memberId,Long missionId); Optional> findOthersArchives(Long memberId, Long missionId) ; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java index a572ae9f..1860601d 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/repository/MissionArchiveCustomRepositoryImpl.java @@ -2,6 +2,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.entity.constant.MissionType; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; @@ -13,7 +14,10 @@ import com.querydsl.core.types.OrderSpecifier; import com.querydsl.core.types.Projections; import com.querydsl.core.types.dsl.Expressions; +import com.querydsl.jpa.JPAExpressions; import com.querydsl.jpa.impl.JPAQueryFactory; +import feign.Param; +import org.springframework.data.jpa.repository.Query; import javax.persistence.EntityManager; import java.util.ArrayList; @@ -22,6 +26,7 @@ import static com.moing.backend.domain.mission.domain.entity.QMission.mission; import static com.moing.backend.domain.missionArchive.domain.entity.QMissionArchive.*; +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; import static javax.swing.Spring.constant; public class MissionArchiveCustomRepositoryImpl implements MissionArchiveCustomRepository { @@ -33,21 +38,57 @@ public MissionArchiveCustomRepositoryImpl(EntityManager em) { } @Override - public Optional> findSingleMissionArchivesByMemberId(Long memberId, Long teamId, MissionStatus status, - MissionArchiveStatus archiveStatus, OrderCondition orderCondition) { + public Optional> findSingleMissionInComplete(Long memberId, Long teamId, MissionStatus status, + OrderCondition orderCondition) { OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); + String missionArchiveStatus = "INCOMPLETE"; return Optional.ofNullable(queryFactory - .select(missionArchive) - .from(missionArchive) + .select(Projections.constructor(SingleMissionBoardRes.class, + mission.id, + mission.dueTo.stringValue(), + mission.title, + Expressions.constant(missionArchiveStatus), + mission.type.stringValue() + )) + .from(mission) + .where(mission.notIn + (JPAExpressions + .select(missionState.mission) + .from(missionState) + .where(missionState.member.memberId.eq(memberId), + missionState.mission.team.teamId.eq(teamId), + missionState.mission.type.eq(MissionType.ONCE), + missionState.mission.status.eq(MissionStatus.SUCCESS) + .or(missionState.mission.status.eq(MissionStatus.ONGOING)) + )), + mission.type.eq(MissionType.ONCE), + mission.team.teamId.eq(teamId)) + .orderBy(orderSpecifiers).fetch()); + + + } + @Override + public Optional> findSingleMissionComplete(Long memberId, Long teamId, MissionStatus status, + OrderCondition orderCondition) { + OrderSpecifier[] orderSpecifiers = createOrderSpecifier(orderCondition); + return Optional.ofNullable(queryFactory + .select(Projections.constructor(SingleMissionBoardRes.class, + mission.id, + mission.dueTo.stringValue(), + mission.title, + missionArchive.status.stringValue(), + mission.type.stringValue() + )) + .from(mission) + .join(mission.missionArchiveList,missionArchive) + .on(missionArchive.member.memberId.eq(memberId)) .where( - missionArchive.mission.team.teamId.eq(teamId), - missionArchive.member.memberId.eq(memberId), - missionArchive.mission.status.eq(status), - missionArchive.mission.type.eq(MissionType.ONCE), - missionArchive.status.eq(archiveStatus) + mission.team.teamId.eq(teamId), + mission.type.eq(MissionType.ONCE), + mission.status.eq(MissionStatus.ONGOING) ) - .orderBy(orderSpecifiers) - .fetch()); + .orderBy(orderSpecifiers).fetch()); + } @@ -56,7 +97,7 @@ private OrderSpecifier[] createOrderSpecifier(OrderCondition orderCondition) { List orderSpecifiers = new ArrayList<>(); if (orderCondition.equals(OrderCondition.DUETO)) { - orderSpecifiers.add(new OrderSpecifier(Order.DESC, missionArchive.mission.dueTo)); + orderSpecifiers.add(new OrderSpecifier(Order.ASC, mission.dueTo)); } else if (orderCondition.equals(OrderCondition.CREATED)) { orderSpecifiers.add(new OrderSpecifier(Order.ASC, missionArchive.createdDate)); } @@ -79,6 +120,7 @@ public Optional> findMyArchives(Long memberId,Long missionI ); } + @Override public Optional> findOthersArchives(Long memberId, Long missionId) { diff --git a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java index 5054882e..d219ef00 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/domain/service/MissionArchiveQueryService.java @@ -3,6 +3,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; +import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; import com.moing.backend.domain.mission.domain.repository.MissionRepository; import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; @@ -39,7 +40,7 @@ public MissionArchive findArchive(Long memberId, Long missionId) { public List findMyArchive(Long memberId, Long missionId) { - Optional> optional = missionArchiveRepository.findArchivesByMissionIdAndMemberId(memberId, missionId); + Optional> optional = missionArchiveRepository.findMyArchives(memberId, missionId); if (optional.isPresent() && optional.get().size() == 0) { return new ArrayList<>(); // throw new NotFoundMissionArchiveException(); @@ -70,12 +71,13 @@ public Boolean isDone(Long memberId, Long missionId) { /** * mission.getTeam() 팀의 단일미션 미션 인증 보드 */ - public List findMySingleMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + public List findMySingleMissionArchives(Long memberId, Long teamId, MissionStatus missionStatus) { + // INCOMPLETE - List incompleteList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, INCOMPLETE, OrderCondition.DUETO) + List incompleteList = missionArchiveRepository.findSingleMissionInComplete(memberId, teamId, missionStatus, OrderCondition.DUETO) .orElseThrow(NotFoundMissionArchiveException::new); - List completeList = missionArchiveRepository.findSingleMissionArchivesByMemberId(memberId, teamId, missionStatus, COMPLETE, OrderCondition.CREATED) + List completeList = missionArchiveRepository.findSingleMissionComplete(memberId, teamId, missionStatus, OrderCondition.CREATED) .orElseThrow(NotFoundMissionArchiveException::new); incompleteList.addAll(completeList); diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java index 21cc7001..82fb4ea7 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionBoardController.java @@ -3,9 +3,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; -import com.moing.backend.domain.missionArchive.application.dto.req.MissionArchiveReq; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveBoardUseCase; import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; diff --git a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java index 639c329a..9895c774 100644 --- a/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java +++ b/src/main/java/com/moing/backend/domain/missionArchive/presentation/MissionGatherController.java @@ -2,18 +2,16 @@ import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; -import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; + import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchivePhotoRes; -import com.moing.backend.domain.missionArchive.application.service.MissionArchiveReadUseCase; + import com.moing.backend.global.config.security.dto.User; import com.moing.backend.global.response.SuccessResponse; import lombok.AllArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.security.core.annotation.AuthenticationPrincipal; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java b/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java new file mode 100644 index 00000000..0e12354f --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/application/dto/MissionStatusRes.java @@ -0,0 +1,8 @@ +package com.moing.backend.domain.missionState.application.dto; + +public class MissionStatusRes { + + private Long done; + private Long total; + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java new file mode 100644 index 00000000..babacbe9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/application/service/MissionStateUseCase.java @@ -0,0 +1,72 @@ +package com.moing.backend.domain.missionState.application.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.mission.domain.entity.constant.MissionType; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.missionState.domain.service.MissionStateSaveService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class MissionStateUseCase { + + // 미션 종료 직전인지 확인 + // missionId, missionstate num mission.team.personum + + private final MissionQueryService missionQueryService; + private final MissionStateQueryService missionStateQueryService; + private final MissionStateSaveService missionStateSaveService; + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; + + + public boolean isAbleToEnd(Long missionId) { + + Mission mission = missionQueryService.findMissionById(missionId); + Long total = totalPeople(mission); + Long done = donePeople(mission); + + log.info("done/total -> "+ done+ total); + + return done == total-1; + + } + + + public Long donePeople(Mission mission) { + return missionStateQueryService.stateCountByMissionId(mission.getId()); + } + + public Long totalPeople(Mission mission) { + return Long.valueOf(mission.getTeam().getNumOfMember()); + + } + + public void updateMissionState(Member member, Mission mission, MissionArchive missionArchive) { + + // 마지막 인증 시 + if (isAbleToEnd(mission.getId())) { + mission.updateStatus(MissionStatus.SUCCESS); + } + + // 미션 인증 상태 저장 + missionStateSaveService.saveMissionState(member,mission, missionArchive.getStatus()); + + + + + } + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java new file mode 100644 index 00000000..788b602c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/MissionState.java @@ -0,0 +1,34 @@ +package com.moing.backend.domain.missionState.domain.entity; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import javax.persistence.*; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Getter +@Builder +public class MissionState extends BaseTimeEntity { + + @Id @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "missionState_id") + private Long id; + + @OneToOne(fetch = FetchType.LAZY) + private Mission mission; + @OneToOne + private Member member; + + @Enumerated(value = EnumType.STRING) + private MissionArchiveStatus status; + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java b/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java new file mode 100644 index 00000000..56f082a8 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/entity/Status.java @@ -0,0 +1,5 @@ +package com.moing.backend.domain.missionState.domain.entity; + +public enum Status { + SUCCESS,FAIL +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java new file mode 100644 index 00000000..8ee3ce0d --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepository.java @@ -0,0 +1,15 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import org.springframework.stereotype.Repository; + +import java.util.List; + +@Repository +public interface MissionStateCustomRepository { + + Long getCountsByMissionId(Long missionId) ; + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java new file mode 100644 index 00000000..114a82cf --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateCustomRepositoryImpl.java @@ -0,0 +1,43 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; + + +import static com.moing.backend.domain.missionState.domain.entity.QMissionState.missionState; + +public class MissionStateCustomRepositoryImpl implements MissionStateCustomRepository { + + private final JPAQueryFactory queryFactory; + + public MissionStateCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + + + @Override + public Long getCountsByMissionId(Long missionId) { + return queryFactory + .select(missionState.count()) + .from(missionState) + .where( + missionState.mission.id.eq(missionId)) + .where( + (missionState.status.eq(MissionArchiveStatus.COMPLETE) + .or( missionState.status.eq(MissionArchiveStatus.SKIP))) + ) + .fetchFirst(); + } + + + + + + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java new file mode 100644 index 00000000..32d06a99 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/repository/MissionStateRepository.java @@ -0,0 +1,9 @@ +package com.moing.backend.domain.missionState.domain.repository; + +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +@Repository +public interface MissionStateRepository extends JpaRepository,MissionStateCustomRepository { +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java new file mode 100644 index 00000000..b5130ee6 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryService.java @@ -0,0 +1,21 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStateQueryService { + + private final MissionStateRepository missionStateRepository; + + public Long stateCountByMissionId(Long missionId) { + return missionStateRepository.getCountsByMissionId(missionId); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java new file mode 100644 index 00000000..1a1fc6e9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/missionState/domain/service/MissionStateSaveService.java @@ -0,0 +1,31 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.member.domain.entity.Member; +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchive; +import com.moing.backend.domain.missionArchive.domain.entity.MissionArchiveStatus; +import com.moing.backend.domain.missionState.domain.entity.MissionState; +import com.moing.backend.domain.missionState.domain.entity.Status; +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; + +import javax.transaction.Transactional; + +@DomainService +@Transactional +@RequiredArgsConstructor +public class MissionStateSaveService { + + private final MissionStateRepository missionStateRepository; + + public void saveMissionState(Member member, Mission mission, MissionArchiveStatus status) { + missionStateRepository.save(MissionState.builder() + .mission(mission) + .member(member) + .status(status) + .build()); + } + +} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java deleted file mode 100644 index b9403968..00000000 --- a/src/main/java/com/moing/backend/domain/score/application/service/ScoreSaveUseCase.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.moing.backend.domain.score.application.service; - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; - -public class ScoreSaveUseCase { - - - -} diff --git a/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java b/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java deleted file mode 100644 index 9e5a60e5..00000000 --- a/src/main/java/com/moing/backend/domain/score/application/service/ScoreUpdateUseCase.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.moing.backend.domain.score.application.service; - -import com.moing.backend.domain.mission.domain.entity.Mission; -import com.moing.backend.domain.mission.domain.entity.constant.MissionStatus; - -public class ScoreUpdateUseCase { - - public int singleMissionDone(Mission mission) { - - if (mission.getStatus() == MissionStatus.END) { - - - } - - return 3; - } -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java b/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java deleted file mode 100644 index 257e500f..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/entity/Score.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.moing.backend.domain.score.domain.entity; - -import lombok.Getter; - -import javax.persistence.Entity; -import javax.persistence.GeneratedValue; -import javax.persistence.GenerationType; -import javax.persistence.Id; - -@Entity -@Getter -public class Score { - - @Id @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - private Long teamId; - private int score; - - public int updateScore(int score) { - return this.score += score; - } -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java b/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java deleted file mode 100644 index 67d1b303..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/repository/ScoreRepository.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.moing.backend.domain.score.domain.repository; - -import com.moing.backend.domain.score.domain.entity.Score; -import org.springframework.data.jpa.repository.JpaRepository; -import org.springframework.data.jpa.repository.Query; - -import java.util.Optional; - - -public interface ScoreRepository extends JpaRepository { - - @Query("select s from Score s where s.teamId = :teamId ") - Score findByTeamId(Long teamId); - -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java deleted file mode 100644 index 983f3604..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreQueryService.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.moing.backend.domain.score.domain.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.repository.ScoreRepository; -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; - -@Service -@RequiredArgsConstructor -public class ScoreQueryService { - - private final ScoreRepository scoreRepository; - - public Score findByTeamId(Long teamId) { - return scoreRepository.findByTeamId(teamId); - } - -} diff --git a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java b/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java deleted file mode 100644 index c2ae310e..00000000 --- a/src/main/java/com/moing/backend/domain/score/domain/service/ScoreSaveService.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.moing.backend.domain.score.domain.service; - -import com.moing.backend.domain.score.domain.entity.Score; -import com.moing.backend.domain.score.domain.repository.ScoreRepository; -import com.moing.backend.global.annotation.DomainService; -import lombok.RequiredArgsConstructor; -import org.springframework.transaction.annotation.Transactional; - -@DomainService -@Transactional -@RequiredArgsConstructor -public class ScoreSaveService { - - private final ScoreRepository scoreRepository; - - public Score save(Score score) { - return scoreRepository.save(score); - } - -} diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java b/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java new file mode 100644 index 00000000..149cd63c --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/dto/TeamScoreRes.java @@ -0,0 +1,16 @@ +package com.moing.backend.domain.teamScore.application.dto; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class TeamScoreRes { + + private Long score; + private Long level; +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java new file mode 100644 index 00000000..7ade209a --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/application/service/TeamScoreLogicUseCase.java @@ -0,0 +1,81 @@ +package com.moing.backend.domain.teamScore.application.service; + + +import com.moing.backend.domain.mission.domain.entity.Mission; +import com.moing.backend.domain.mission.domain.service.MissionQueryService; +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.service.MissionStateQueryService; +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.service.TeamScoreQueryService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +@Slf4j +@Service +@Transactional +@RequiredArgsConstructor +public class TeamScoreLogicUseCase { + + private final TeamGetService teamGetService; + private final MissionQueryService missionQueryService; + private final TeamScoreQueryService teamScoreQueryService; + private final MissionStateQueryService missionStateQueryService; + + public TeamScoreRes getTeamScoreInfo(Long teamId) { + + return TeamScoreRes.builder() + .score(getScore(teamId)) + .level(getLevel(teamId)) + .build() + ; + } + + public Long updateSingleScore(Long missionId) { + Mission mission = missionQueryService.findMissionById(missionId); + Team team = mission.getTeam(); + + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + + teamScore.updateScore(getScoreByMission(mission)); + teamScore.levelUp(); + return teamScore.getScore(); + } + + public Long getScore(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getScore(); + } + + public Long getLevel(Long teamId) { + return teamScoreQueryService.findTeamScoreByTeam(teamId).getLevel(); + } + + public Long getScoreByMission(Mission mission) { + Long total = totalPeople(mission); + Long done = donePeople(mission); + + return (done / total * 100) / 5 ; + + } + + public Long donePeople(Mission mission) { + + log.info("done people-> {}", missionStateQueryService.stateCountByMissionId(mission.getId())); + return missionStateQueryService.stateCountByMissionId(mission.getId()); + } + + public Long totalPeople(Mission mission) { + return Long.valueOf(mission.getTeam().getNumOfMember()); + + } + + + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java new file mode 100644 index 00000000..3b40e6ea --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/entity/TeamScore.java @@ -0,0 +1,54 @@ +package com.moing.backend.domain.teamScore.domain.entity; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.global.entity.BaseTimeEntity; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import javax.persistence.*; + +@Entity +@Getter +@RequiredArgsConstructor +public class TeamScore extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "teamScore_id") + private Long id; + + @OneToOne + private Team team; + + private Long score; + + private Long level; + + @Builder + public TeamScore(Team team, Long score,Long level) { + this.team = team; + this.score = score; + this.level = level; + } + + public void updateScore(Long score) { + + this.score += score; + } + + public void levelUp() { + final int[] steps = {0, 2, 10, 25, 45, 100}; + + for (int i = 0; i < 5; i++) { + if (steps[i] < this.level && this.level < steps[i + 1]) { + if (20 + i * 15 <= score) { + this.level+=1; + this.score -= score - (20 + i * 15); + return; + } + } + } + + } +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java new file mode 100644 index 00000000..1b08b750 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepository.java @@ -0,0 +1,11 @@ +package com.moing.backend.domain.teamScore.domain.repository; + + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; + +public interface TeamScoreCustomRepository { + + TeamScore findTeamScoreByTeam(Long teamId); + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java new file mode 100644 index 00000000..8e038986 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreCustomRepositoryImpl.java @@ -0,0 +1,28 @@ +package com.moing.backend.domain.teamScore.domain.repository; + +import static com.moing.backend.domain.teamScore.domain.entity.QTeamScore.teamScore; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.querydsl.jpa.impl.JPAQueryFactory; + +import javax.persistence.EntityManager; + +public class TeamScoreCustomRepositoryImpl implements TeamScoreCustomRepository { + + + private final JPAQueryFactory queryFactory; + + public TeamScoreCustomRepositoryImpl(EntityManager entityManager) { + this.queryFactory = new JPAQueryFactory(entityManager); + } + + @Override + public TeamScore findTeamScoreByTeam(Long teamId) { + return queryFactory + .selectFrom(teamScore) + .where(teamScore.team.teamId.eq(teamId)).fetchFirst(); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java new file mode 100644 index 00000000..14771e08 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/repository/TeamScoreRepository.java @@ -0,0 +1,7 @@ +package com.moing.backend.domain.teamScore.domain.repository; + +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface TeamScoreRepository extends JpaRepository , TeamScoreCustomRepository{ +} \ No newline at end of file diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java new file mode 100644 index 00000000..9f1f1e29 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreQueryService.java @@ -0,0 +1,26 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreQueryService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + + public TeamScore findTeamScoreByTeam(Long teamId) { + + return teamScoreRepository.findTeamScoreByTeam(teamId); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java new file mode 100644 index 00000000..c265cef9 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreSaveService.java @@ -0,0 +1,30 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreSaveService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + + public TeamScore save(Long teamId, Long score) { + Team team = teamGetService.getTeamByTeamId(teamId); + + return teamScoreRepository.save(TeamScore.builder() + .team(team) + .score(score) + .build()); + } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java new file mode 100644 index 00000000..4ec692e1 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/domain/service/TeamScoreUpdateService.java @@ -0,0 +1,33 @@ +package com.moing.backend.domain.teamScore.domain.service; + +import com.moing.backend.domain.team.domain.entity.Team; +import com.moing.backend.domain.team.domain.service.TeamGetService; +import com.moing.backend.domain.teamScore.domain.entity.TeamScore; +import com.moing.backend.domain.teamScore.domain.repository.TeamScoreRepository; +import com.moing.backend.global.annotation.DomainService; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + + +@DomainService +@Transactional +@RequiredArgsConstructor +public class TeamScoreUpdateService { + + private final TeamScoreRepository teamScoreRepository; + private final TeamGetService teamGetService; + private final TeamScoreQueryService teamScoreQueryService; + + public TeamScore update(Long teamId, Long score) { + Team team = teamGetService.getTeamByTeamId(teamId); + + TeamScore teamScore = teamScoreQueryService.findTeamScoreByTeam(team.getTeamId()); + + teamScore.updateScore(score); + + return teamScore; + + } + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java new file mode 100644 index 00000000..fe4ddf53 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/presentation/TeamScoreController.java @@ -0,0 +1,46 @@ +package com.moing.backend.domain.teamScore.presentation; + +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import com.moing.backend.global.config.security.dto.User; +import com.moing.backend.global.response.SuccessResponse; +import lombok.AllArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; +import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; + +@RestController +@AllArgsConstructor +@RequestMapping("/api/team/{teamId}") +public class TeamScoreController { + + private final TeamScoreLogicUseCase teamScoreLogicUseCase; + + /** + * 팀별 불 레벨/경험치 조회 + * [GET] my-repeat + * 작성자 : 정승연 + */ + + @GetMapping("/my-fire") + public ResponseEntity> getTeamScore(@PathVariable("teamId") Long teamId, @AuthenticationPrincipal User user) { + return ResponseEntity.ok(SuccessResponse.create(GET_TEAMSCORE_SUCCESS.getMessage(), this.teamScoreLogicUseCase.getTeamScoreInfo(teamId))); + } + + + + + +} diff --git a/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java b/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java new file mode 100644 index 00000000..21d75493 --- /dev/null +++ b/src/main/java/com/moing/backend/domain/teamScore/presentation/constant/TeamScoreResponseMessage.java @@ -0,0 +1,13 @@ +package com.moing.backend.domain.teamScore.presentation.constant; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum TeamScoreResponseMessage { + GET_TEAMSCORE_SUCCESS("팀 경험치/레벨 조회를 완료 했습니다"); + + private final String message; +} + diff --git a/src/main/java/com/moing/backend/global/response/ErrorCode.java b/src/main/java/com/moing/backend/global/response/ErrorCode.java index 2f5ddd21..f3f29b6f 100644 --- a/src/main/java/com/moing/backend/global/response/ErrorCode.java +++ b/src/main/java/com/moing/backend/global/response/ErrorCode.java @@ -28,6 +28,7 @@ public enum ErrorCode { //미션 관련 에러코드 NO_ACCESS_CREATE_MISSION("M0001", "소모임장만 미션을 생성할 수 있습니다."), NOT_FOUND_MISSION("M0002", "미션을 찾을 수 없습니다."), + NOT_FOUND_END_MISSION("M0002", "기한이 지난 미션을 찾을 수 없습니다."), NOT_FOUND_MISSION_ARCHIVE("MA0001", "아직 미션을 제출하지 않았습니다."), NO_MORE_ARCHIVE_ERROR("MA0001", "지정한 횟수 이상 미션을 인증할 수 없습니다."), diff --git a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java index 5cdfd3fe..953a9d2b 100644 --- a/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java +++ b/src/test/java/com/moing/backend/domain/missionArchive/representation/MissionBoardControllerTest.java @@ -4,8 +4,7 @@ import com.moing.backend.domain.mission.application.dto.res.FinishMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.RepeatMissionBoardRes; import com.moing.backend.domain.mission.application.dto.res.SingleMissionBoardRes; -import com.moing.backend.domain.mission.application.service.MissionArchiveBoardUseCase; -import com.moing.backend.domain.missionArchive.application.dto.res.MissionArchiveRes; +import com.moing.backend.domain.missionArchive.application.service.MissionArchiveBoardUseCase; import com.moing.backend.domain.missionArchive.presentation.MissionBoardController; import org.assertj.core.util.Lists; import org.junit.jupiter.api.Test; @@ -19,7 +18,6 @@ import java.util.List; import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.*; -import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; diff --git a/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java new file mode 100644 index 00000000..91a716c3 --- /dev/null +++ b/src/test/java/com/moing/backend/domain/missionState/domain/service/MissionStateQueryServiceTest.java @@ -0,0 +1,35 @@ +package com.moing.backend.domain.missionState.domain.service; + +import com.moing.backend.domain.missionState.application.service.MissionStateUseCase; +import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepository; +import com.moing.backend.domain.missionState.domain.repository.MissionStateCustomRepositoryImpl; +import com.moing.backend.domain.missionState.domain.repository.MissionStateRepository; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; + +import javax.persistence.EntityManager; + +import static org.junit.jupiter.api.Assertions.*; + +@SpringBootTest +class MissionStateQueryServiceTest { + + + @MockBean + MissionStateQueryService missionStateQueryService ; + @MockBean + MissionStateCustomRepositoryImpl missionStateCustomRepository ; + + + @Test + public void missionDonePeople() { + System.out.println(missionStateQueryService.stateCountByMissionId(4L)); + } + + + + + +} \ No newline at end of file diff --git a/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java new file mode 100644 index 00000000..1ac4977b --- /dev/null +++ b/src/test/java/com/moing/backend/domain/teamScore/presentation/TeamScoreControllerTest.java @@ -0,0 +1,81 @@ +package com.moing.backend.domain.teamScore.presentation; + +import com.moing.backend.config.CommonControllerTest; +import com.moing.backend.domain.mission.application.dto.res.GatherRepeatMissionRes; +import com.moing.backend.domain.mission.application.dto.res.GatherSingleMissionRes; +import com.moing.backend.domain.mission.application.service.MissionGatherBoardUseCase; +import com.moing.backend.domain.missionArchive.presentation.MissionGatherController; +import com.moing.backend.domain.teamScore.application.dto.TeamScoreRes; +import com.moing.backend.domain.teamScore.application.service.TeamScoreLogicUseCase; +import org.assertj.core.util.Lists; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; +import org.springframework.restdocs.mockmvc.RestDocumentationRequestBuilders; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.result.MockMvcResultMatchers; + +import java.util.List; + +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_REPEAT_MISSION_SUCCESS; +import static com.moing.backend.domain.missionArchive.domain.constant.MissionArchiveResponseMessage.ACTIVE_SINGLE_MISSION_SUCCESS; +import static com.moing.backend.domain.teamScore.presentation.constant.TeamScoreResponseMessage.GET_TEAMSCORE_SUCCESS; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.springframework.restdocs.headers.HeaderDocumentation.headerWithName; +import static org.springframework.restdocs.headers.HeaderDocumentation.requestHeaders; +import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; +import static org.springframework.restdocs.payload.PayloadDocumentation.responseFields; + +@WebMvcTest(TeamScoreController.class) +public class TeamScoreControllerTest extends CommonControllerTest { + + + @MockBean + private TeamScoreLogicUseCase teamScoreLogicUseCase; + + @Test + public void 팀별_불_레벨_경험치_조회() throws Exception { + //given + + TeamScoreRes output = TeamScoreRes.builder() + .score(1L) + .level(1L) + .build(); + + given(teamScoreLogicUseCase.getTeamScoreInfo(any())).willReturn(output); + + Long teamId = 1L; + //when + ResultActions actions = mockMvc.perform(RestDocumentationRequestBuilders. + get("/api/team/{teamId}/my-fire",teamId) + .header("Authorization", "Bearer ACCESS_TOKEN") + .contentType(MediaType.APPLICATION_JSON) + + ); + + //then + actions + .andExpect(MockMvcResultMatchers.status().isOk()) + .andDo( + restDocs.document( + requestHeaders( + headerWithName("Authorization").description("접근 토큰") + ), + + responseFields( + fieldWithPath("isSuccess").description("true"), + fieldWithPath("message").description(GET_TEAMSCORE_SUCCESS.getMessage()), + fieldWithPath("data.score").description("팀 경험치"), + fieldWithPath("data.level").description("팀 불 레벨") + + ) + ) + ) + .andReturn(); + + } + + +} \ No newline at end of file