Skip to content

Commit

Permalink
fix: MemberServie confilt 해결
Browse files Browse the repository at this point in the history
  • Loading branch information
parksey committed Nov 6, 2023
2 parents 0759ebb + 40e5c1a commit 9080613
Show file tree
Hide file tree
Showing 25 changed files with 719 additions and 33 deletions.
14 changes: 13 additions & 1 deletion src/main/java/com/moabam/api/application/MemberService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import static com.moabam.global.error.model.ErrorMessage.*;

import java.time.LocalDate;
import java.util.List;
import java.util.Optional;

import org.apache.commons.lang3.RandomStringUtils;
Expand All @@ -12,6 +13,7 @@

import com.moabam.api.domain.entity.Member;
import com.moabam.api.domain.repository.MemberRepository;
import com.moabam.api.domain.repository.MemberSearchRepository;
import com.moabam.api.dto.AuthorizationTokenInfoResponse;
import com.moabam.api.dto.LoginResponse;
import com.moabam.api.dto.MemberMapper;
Expand All @@ -25,6 +27,7 @@
public class MemberService {

private final MemberRepository memberRepository;
private final MemberSearchRepository memberSearchRepository;

public Member getById(Long memberId) {
return memberRepository.findById(memberId)
Expand Down Expand Up @@ -57,4 +60,13 @@ private Member signUp(long socialId) {
private String createRandomNickName() {
return RandomStringUtils.randomAlphanumeric(RANDOM_NICKNAME_SIZE) + UNDER_BAR + LocalDate.now();
}
}

public Member getManager(Long roomId) {
return memberSearchRepository.findManager(roomId)
.orElseThrow(() -> new NotFoundException(MEMBER_NOT_FOUND));
}

public List<Member> getRoomMembers(List<Long> memberIds) {
return memberRepository.findAllById(memberIds);
}
}
157 changes: 145 additions & 12 deletions src/main/java/com/moabam/api/application/RoomService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,40 @@
import static com.moabam.api.domain.entity.enums.RoomType.*;
import static com.moabam.global.error.model.ErrorMessage.*;

import java.time.LocalDate;
import java.time.Period;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.moabam.api.domain.entity.Certification;
import com.moabam.api.domain.entity.DailyMemberCertification;
import com.moabam.api.domain.entity.DailyRoomCertification;
import com.moabam.api.domain.entity.Member;
import com.moabam.api.domain.entity.Participant;
import com.moabam.api.domain.entity.Room;
import com.moabam.api.domain.entity.Routine;
import com.moabam.api.domain.entity.enums.RoomType;
import com.moabam.api.domain.repository.CertificationsMapper;
import com.moabam.api.domain.repository.CertificationsSearchRepository;
import com.moabam.api.domain.repository.ParticipantRepository;
import com.moabam.api.domain.repository.ParticipantSearchRepository;
import com.moabam.api.domain.repository.RoomRepository;
import com.moabam.api.domain.repository.RoutineRepository;
import com.moabam.api.domain.repository.RoutineSearchRepository;
import com.moabam.api.dto.CertificationImageResponse;
import com.moabam.api.dto.CreateRoomRequest;
import com.moabam.api.dto.EnterRoomRequest;
import com.moabam.api.dto.ModifyRoomRequest;
import com.moabam.api.dto.RoomDetailsResponse;
import com.moabam.api.dto.RoomMapper;
import com.moabam.api.dto.RoutineMapper;
import com.moabam.api.dto.RoutineResponse;
import com.moabam.api.dto.TodayCertificateRankResponse;
import com.moabam.global.error.exception.BadRequestException;
import com.moabam.global.error.exception.ForbiddenException;
import com.moabam.global.error.exception.NotFoundException;
Expand All @@ -35,14 +50,16 @@ public class RoomService {

private final RoomRepository roomRepository;
private final RoutineRepository routineRepository;
private final RoutineSearchRepository routineSearchRepository;
private final ParticipantRepository participantRepository;
private final ParticipantSearchRepository participantSearchRepository;
private final CertificationsSearchRepository certificationsSearchRepository;
private final MemberService memberService;

@Transactional
public void createRoom(Long memberId, CreateRoomRequest createRoomRequest) {
Room room = RoomMapper.toRoomEntity(createRoomRequest);
List<Routine> routines = RoomMapper.toRoutineEntity(room, createRoomRequest.routines());
List<Routine> routines = RoutineMapper.toRoutineEntities(room, createRoomRequest.routines());
Participant participant = Participant.builder()
.room(room)
.memberId(memberId)
Expand All @@ -62,16 +79,17 @@ public void modifyRoom(Long memberId, Long roomId, ModifyRoomRequest modifyRoomR
throw new ForbiddenException(ROOM_MODIFY_UNAUTHORIZED_REQUEST);
}

Room room = getRoom(roomId);
Room room = participant.getRoom();
room.changeTitle(modifyRoomRequest.title());
room.changeAnnouncement(modifyRoomRequest.announcement());
room.changePassword(modifyRoomRequest.password());
room.changeCertifyTime(modifyRoomRequest.certifyTime());
room.changeMaxCount(modifyRoomRequest.maxUserCount());
}

@Transactional
public void enterRoom(Long memberId, Long roomId, EnterRoomRequest enterRoomRequest) {
Room room = getRoom(roomId);
Room room = roomRepository.findById(roomId).orElseThrow(() -> new NotFoundException(ROOM_NOT_FOUND));
validateRoomEnter(memberId, enterRoomRequest.password(), room);

room.increaseCurrentUserCount();
Expand All @@ -95,7 +113,6 @@ public void exitRoom(Long memberId, Long roomId) {

decreaseRoomCount(memberId, room.getRoomType());
participant.removeRoom();
participantRepository.flush();
participantRepository.delete(participant);

if (!participant.isManager()) {
Expand All @@ -107,30 +124,43 @@ public void exitRoom(Long memberId, Long roomId) {
roomRepository.delete(room);
}

public RoomDetailsResponse getRoomDetails(Long memberId, Long roomId) {
LocalDate today = LocalDate.now();
Participant participant = getParticipant(memberId, roomId);
Room room = participant.getRoom();

String managerNickname = memberService.getManager(roomId).getNickname();
List<DailyMemberCertification> dailyMemberCertifications =
certificationsSearchRepository.findSortedDailyMemberCertifications(roomId, today);
List<RoutineResponse> routineResponses = getRoutineResponses(roomId);
List<TodayCertificateRankResponse> todayCertificateRankResponses = getTodayCertificateRankResponses(roomId,
routineResponses, dailyMemberCertifications, today);
List<LocalDate> certifiedDates = getCertifiedDates(roomId, today);
double completePercentage = calculateCompletePercentage(dailyMemberCertifications.size(),
room.getCurrentUserCount());

return RoomMapper.toRoomDetailsResponse(room, managerNickname, routineResponses, certifiedDates,
todayCertificateRankResponses, completePercentage);
}

public void validateRoomById(Long roomId) {
if (!roomRepository.existsById(roomId)) {
throw new NotFoundException(ROOM_NOT_FOUND);
}
}

private Participant getParticipant(Long memberId, Long roomId) {
return participantSearchRepository.findParticipant(memberId, roomId)
return participantSearchRepository.findOne(memberId, roomId)
.orElseThrow(() -> new NotFoundException(PARTICIPANT_NOT_FOUND));
}

private Room getRoom(Long roomId) {
return roomRepository.findById(roomId).orElseThrow(() -> new NotFoundException(ROOM_NOT_FOUND));
}

private void validateRoomEnter(Long memberId, String requestPassword, Room room) {
if (!isEnterRoomAvailable(memberId, room.getRoomType())) {
throw new BadRequestException(MEMBER_ROOM_EXCEED);
}

if (!StringUtils.isEmpty(requestPassword) && !room.getPassword().equals(requestPassword)) {
throw new BadRequestException(WRONG_ROOM_PASSWORD);
}

if (room.getCurrentUserCount() == room.getMaxUserCount()) {
throw new BadRequestException(ROOM_MAX_USER_REACHED);
}
Expand All @@ -142,7 +172,6 @@ private boolean isEnterRoomAvailable(Long memberId, RoomType roomType) {
if (roomType.equals(MORNING) && member.getCurrentMorningCount() >= 3) {
return false;
}

if (roomType.equals(NIGHT) && member.getCurrentNightCount() >= 3) {
return false;
}
Expand Down Expand Up @@ -171,4 +200,108 @@ private void decreaseRoomCount(Long memberId, RoomType roomType) {

member.exitNightRoom();
}

private List<RoutineResponse> getRoutineResponses(Long roomId) {
List<Routine> roomRoutines = routineSearchRepository.findByRoomId(roomId);

return RoutineMapper.toRoutineResponses(roomRoutines);
}

private List<TodayCertificateRankResponse> getTodayCertificateRankResponses(Long roomId,
List<RoutineResponse> routines, List<DailyMemberCertification> dailyMemberCertifications, LocalDate today) {

List<TodayCertificateRankResponse> responses = new ArrayList<>();
List<Long> routineIds = routines.stream()
.map(RoutineResponse::routineId)
.toList();
List<Certification> certifications = certificationsSearchRepository.findCertifications(
routineIds,
today);
List<Participant> participants = participantSearchRepository.findParticipants(roomId);
List<Member> members = memberService.getRoomMembers(participants.stream()
.map(Participant::getMemberId)
.toList());

addCompletedMembers(responses, dailyMemberCertifications, members, certifications, participants, today);
addUncompletedMembers(responses, dailyMemberCertifications, members, participants, today);

return responses;
}

private void addCompletedMembers(List<TodayCertificateRankResponse> responses,
List<DailyMemberCertification> dailyMemberCertifications, List<Member> members,
List<Certification> certifications, List<Participant> participants, LocalDate today) {

int rank = 1;

for (DailyMemberCertification certification : dailyMemberCertifications) {
Member member = members.stream()
.filter(m -> m.getId().equals(certification.getMemberId()))
.findAny()
.orElseThrow(() -> new NotFoundException(ROOM_DETAILS_ERROR));

int contributionPoint = calculateContributionPoint(member.getId(), participants, today);
List<CertificationImageResponse> certificationImageResponses =
CertificationsMapper.toCertificateImageResponses(member.getId(), certifications);

TodayCertificateRankResponse response = CertificationsMapper.toTodayCertificateRankResponse(
rank, member, contributionPoint, "https://~awake", "https://~sleep", certificationImageResponses);

rank += 1;
responses.add(response);
}
}

private void addUncompletedMembers(List<TodayCertificateRankResponse> responses,
List<DailyMemberCertification> dailyMemberCertifications, List<Member> members,
List<Participant> participants, LocalDate today) {

List<Long> allMemberIds = participants.stream()
.map(Participant::getMemberId)
.collect(Collectors.toList());

List<Long> certifiedMemberIds = dailyMemberCertifications.stream()
.map(DailyMemberCertification::getMemberId)
.toList();

allMemberIds.removeAll(certifiedMemberIds);

for (Long memberId : allMemberIds) {
Member member = members.stream()
.filter(m -> m.getId().equals(memberId))
.findAny()
.orElseThrow(() -> new NotFoundException(ROOM_DETAILS_ERROR));

int contributionPoint = calculateContributionPoint(memberId, participants, today);

TodayCertificateRankResponse response = CertificationsMapper.toTodayCertificateRankResponse(
500, member, contributionPoint, "https://~awake", "https://~sleep", null);

responses.add(response);
}
}

private int calculateContributionPoint(Long memberId, List<Participant> participants, LocalDate today) {
Participant participant = participants.stream()
.filter(p -> p.getMemberId().equals(memberId))
.findAny()
.orElseThrow(() -> new NotFoundException(ROOM_DETAILS_ERROR));

int participatedDays = Period.between(participant.getCreatedAt().toLocalDate(), today).getDays() + 1;

return (int)(((double)participant.getCertifyCount() / participatedDays) * 100);
}

private List<LocalDate> getCertifiedDates(Long roomId, LocalDate today) {
List<DailyRoomCertification> certifications = certificationsSearchRepository.findDailyRoomCertifications(
roomId, today);

return certifications.stream().map(DailyRoomCertification::getCertifiedAt).toList();
}

private double calculateCompletePercentage(int certifiedMembersCount, int currentsMembersCount) {
double completePercentage = ((double)certifiedMembersCount / currentsMembersCount) * 100;

return Math.round(completePercentage * 100) / 100.0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package com.moabam.api.domain.entity;

import static java.util.Objects.*;

import com.moabam.global.common.entity.BaseTimeEntity;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.JoinColumn;
import jakarta.persistence.ManyToOne;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(name = "daily_member_certification") // 매일 사용자가 방에 인증을 완료했는지 -> createdAt으로 인증 시각 확인
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DailyMemberCertification extends BaseTimeEntity {

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

@Column(name = "member_id", nullable = false, updatable = false)
private Long memberId;

@Column(name = "room_id", nullable = false, updatable = false)
private Long roomId;

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "participant_id") // Participant createdAt으로 방 참여 시작 날짜 확인, certifyCount 가져다가 쓰기
private Participant participant;

@Builder
private DailyMemberCertification(Long id, Long memberId, Long roomId, Participant participant) {
this.id = id;
this.memberId = requireNonNull(memberId);
this.roomId = requireNonNull(roomId);
this.participant = requireNonNull(participant);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.moabam.api.domain.entity;

import static java.util.Objects.*;

import java.time.LocalDate;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AccessLevel;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Entity
@Getter
@Table(name = "daily_room_certification") // 매일 방이 인증을 완료했는지 -> certifiedAt으로 인증 날짜 확인
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class DailyRoomCertification {

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

@Column(name = "room_id", nullable = false, updatable = false)
private Long roomId;

@Column(name = "certified_at", nullable = false, updatable = false)
private LocalDate certifiedAt;

@Builder
private DailyRoomCertification(Long id, Long roomId, LocalDate certifiedAt) {
this.id = id;
this.roomId = requireNonNull(roomId);
this.certifiedAt = requireNonNull(certifiedAt);
}
}
Loading

0 comments on commit 9080613

Please sign in to comment.