diff --git a/src/main/java/com/avab/avab/converter/FlowConverter.java b/src/main/java/com/avab/avab/converter/FlowConverter.java index 085ed2f..01d2cf0 100644 --- a/src/main/java/com/avab/avab/converter/FlowConverter.java +++ b/src/main/java/com/avab/avab/converter/FlowConverter.java @@ -9,6 +9,7 @@ import com.avab.avab.domain.CustomRecreation; import com.avab.avab.domain.Flow; +import com.avab.avab.domain.Flow.FlowBuilder; import com.avab.avab.domain.FlowAge; import com.avab.avab.domain.FlowGender; import com.avab.avab.domain.Recreation; @@ -86,74 +87,15 @@ public static Flow toFlow( List recreationKeywordList, List recreationPurposeList) { - Flow flow = - Flow.builder() - .participants(request.getParticipants()) - .totalPlayTime(request.getTotalPlayTime()) - .title(request.getTitle()) - .imageUrl(imageUrl) - .author(user) - .build(); + Flow flow = buildFlow(null, request, user, imageUrl); - List flowRecreationList = - request.getRecreationSpecList().stream() - .map( - spec -> { - // Recreation에 대한 FlowRecreation 생성 - if (recreationMap.containsKey(spec.getSeq())) { - return FlowRecreation.builder() - .flow(flow) - .recreation(recreationMap.get(spec.getSeq())) - .customPlayTime(spec.getCustomPlayTime()) - .seq(spec.getSeq()) - .build(); - } - // CustomRecreation에 대한 FlowRecreation 생성 - return FlowRecreation.builder() - .flow(flow) - .customRecreation( - customRecreationMap.get(spec.getSeq())) - .customPlayTime(spec.getCustomPlayTime()) - .seq(spec.getSeq()) - .build(); - }) - .toList(); - - List flowRecreationKeywordList = - recreationKeywordList.stream() - .map( - recreationKeyword -> - FlowRecreationKeyword.builder() - .flow(flow) - .keyword(recreationKeyword) - .build()) - .toList(); - - List flowRecreationPurposeList = - recreationPurposeList.stream() - .map( - recreationPurpose -> - FlowRecreationPurpose.builder() - .flow(flow) - .purpose(recreationPurpose) - .build()) - .toList(); - - List flowAgeList = - request.getAgeList().stream() - .map(age -> FlowAge.builder().age(age).flow(flow).build()) - .toList(); - - List flowGenderList = - request.getGenderList().stream() - .map(gender -> FlowGender.builder().flow(flow).gender(gender).build()) - .toList(); - - flow.getFlowRecreationList().addAll(flowRecreationList); - flow.getFlowRecreationKeywordList().addAll(flowRecreationKeywordList); - flow.getFlowRecreationPurposeList().addAll(flowRecreationPurposeList); - flow.getAgeList().addAll(flowAgeList); - flow.getGenderList().addAll(flowGenderList); + populateFlowDetails( + request, + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList, + flow); return flow; } @@ -284,76 +226,127 @@ public static Flow toUpdateFlow( Map customRecreationMap, List recreationKeywordList, List recreationPurposeList) { - Flow flow = + Flow flow = buildFlow(flowId, request, user, imageUrl); + + populateFlowDetails( + request, + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList, + flow); + + return flow; + } + + private static Flow buildFlow(Long flowId, PostFlowDTO request, User user, String imageUrl) { + FlowBuilder builder = Flow.builder() - .id(flowId) .participants(request.getParticipants()) .totalPlayTime(request.getTotalPlayTime()) - .imageUrl(imageUrl) .title(request.getTitle()) - .author(user) - .build(); - - List flowRecreationList = - request.getRecreationSpecList().stream() - .map( - spec -> { - // Recreation에 대한 FlowRecreation 생성 - if (recreationMap.containsKey(spec.getSeq())) { - return FlowRecreation.builder() - .flow(flow) - .recreation(recreationMap.get(spec.getSeq())) - .customPlayTime(spec.getCustomPlayTime()) - .seq(spec.getSeq()) - .build(); - } - // CustomRecreation에 대한 FlowRecreation 생성 - return FlowRecreation.builder() - .flow(flow) - .customRecreation( - customRecreationMap.get(spec.getSeq())) - .customPlayTime(spec.getCustomPlayTime()) - .seq(spec.getSeq()) - .build(); - }) - .toList(); - - List flowRecreationKeywordList = - recreationKeywordList.stream() - .map( - recreationKeyword -> - FlowRecreationKeyword.builder() - .flow(flow) - .keyword(recreationKeyword) - .build()) - .toList(); + .imageUrl(imageUrl) + .author(user); - List flowRecreationPurposeList = - recreationPurposeList.stream() - .map( - recreationPurpose -> - FlowRecreationPurpose.builder() - .flow(flow) - .purpose(recreationPurpose) - .build()) - .toList(); + if (flowId != null) { + builder.id(flowId); + } - List flowAgeList = - request.getAgeList().stream() - .map(age -> FlowAge.builder().age(age).flow(flow).build()) - .toList(); + return builder.build(); + } - List flowGenderList = - request.getGenderList().stream() - .map(gender -> FlowGender.builder().flow(flow).gender(gender).build()) - .toList(); + private static void populateFlowDetails( + PostFlowDTO request, + Map recreationMap, + Map customRecreationMap, + List recreationKeywordList, + List recreationPurposeList, + Flow flow) { + List recreations = + getFlowRecreations(request, recreationMap, customRecreationMap, flow); + List keywords = + getFlowRecreationKeywords(recreationKeywordList, flow); + List purposes = + getFlowRecreationPurposes(recreationPurposeList, flow); + List ages = getFlowAges(request.getAgeList(), flow); + List genders = getFlowGenders(request.getGenderList(), flow); + + attachFlowDetails(flow, recreations, keywords, purposes, ages, genders); + } + private static void attachFlowDetails( + Flow flow, + List flowRecreationList, + List flowRecreationKeywordList, + List flowRecreationPurposeList, + List flowAgeList, + List flowGenderList) { flow.getFlowRecreationList().addAll(flowRecreationList); flow.getFlowRecreationKeywordList().addAll(flowRecreationKeywordList); flow.getFlowRecreationPurposeList().addAll(flowRecreationPurposeList); flow.getAgeList().addAll(flowAgeList); flow.getGenderList().addAll(flowGenderList); + } - return flow; + private static List getFlowRecreations( + PostFlowDTO request, + Map recreationMap, + Map customRecreationMap, + Flow flow) { + return request.getRecreationSpecList().stream() + .map( + spec -> { + // Recreation에 대한 FlowRecreation 생성 + if (recreationMap.containsKey(spec.getSeq())) { + return FlowRecreation.builder() + .flow(flow) + .recreation(recreationMap.get(spec.getSeq())) + .customPlayTime(spec.getCustomPlayTime()) + .seq(spec.getSeq()) + .build(); + } + // CustomRecreation에 대한 FlowRecreation 생성 + return FlowRecreation.builder() + .flow(flow) + .customRecreation(customRecreationMap.get(spec.getSeq())) + .customPlayTime(spec.getCustomPlayTime()) + .seq(spec.getSeq()) + .build(); + }) + .toList(); + } + + private static List getFlowRecreationKeywords( + List recreationKeywordList, Flow flow) { + return recreationKeywordList.stream() + .map( + recreationKeyword -> + FlowRecreationKeyword.builder() + .flow(flow) + .keyword(recreationKeyword) + .build()) + .toList(); + } + + private static List getFlowRecreationPurposes( + List recreationPurposeList, Flow flow) { + return recreationPurposeList.stream() + .map( + recreationPurpose -> + FlowRecreationPurpose.builder() + .flow(flow) + .purpose(recreationPurpose) + .build()) + .toList(); + } + + private static List getFlowAges(List ages, Flow flow) { + return ages.stream().map(age -> FlowAge.builder().age(age).flow(flow).build()).toList(); + } + + private static List getFlowGenders(List genders, Flow flow) { + return genders.stream() + .map(gender -> FlowGender.builder().flow(flow).gender(gender).build()) + .toList(); } } diff --git a/src/main/java/com/avab/avab/repository/FlowCustomRepositoryImpl.java b/src/main/java/com/avab/avab/repository/FlowCustomRepositoryImpl.java index 3486588..644dea2 100644 --- a/src/main/java/com/avab/avab/repository/FlowCustomRepositoryImpl.java +++ b/src/main/java/com/avab/avab/repository/FlowCustomRepositoryImpl.java @@ -65,9 +65,10 @@ public List recommendFlows( purposesForComparison.stream().filter(purpose::contains).count(); // 시간(필수) 비교 + Integer nowTotalPlayTime = nowFlow.getTotalPlayTime(); long loePlayTime = - nowFlow.getTotalPlayTime() <= totalPlayTime - ? -Math.abs(nowFlow.getTotalPlayTime() - totalPlayTime) + (nowTotalPlayTime != null && nowTotalPlayTime <= totalPlayTime) + ? -Math.abs(nowTotalPlayTime - totalPlayTime) : -10000; // 겹치는 키워드 체크 @@ -84,9 +85,12 @@ public List recommendFlows( : 0L; // 인원 + Integer nowParticipants = nowFlow.getParticipants(); int participantsMatch = - participant != null && participant > nowFlow.getParticipants() - ? participant - nowFlow.getParticipants() + (participant != null + && nowParticipants != null + && participant > nowParticipants) + ? participant - nowParticipants : 0; // 연령대 겹치는 개수 확인 diff --git a/src/main/java/com/avab/avab/service/impl/FlowServiceImpl.java b/src/main/java/com/avab/avab/service/impl/FlowServiceImpl.java index 798fa0a..d4ff20f 100644 --- a/src/main/java/com/avab/avab/service/impl/FlowServiceImpl.java +++ b/src/main/java/com/avab/avab/service/impl/FlowServiceImpl.java @@ -7,6 +7,7 @@ import java.util.Optional; import java.util.Random; +import org.jetbrains.annotations.Nullable; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; @@ -143,10 +144,7 @@ public void incrementViewCountById(Long flowId, Long viewCount) { @Override @Transactional public Boolean toggleScrapeFlow(User user, Long flowId) { - Flow flow = - flowRepository - .findById(flowId) - .orElseThrow(() -> new FlowException(ErrorStatus.FLOW_NOT_FOUND)); + Flow flow = getFlow(flowId); Optional flowFavorite = flowScrapRepository.findByFlowAndUser(flow, user); if (flowFavorite.isPresent()) { @@ -165,77 +163,27 @@ public Boolean toggleScrapeFlow(User user, Long flowId) { @Transactional public Flow postFlow(PostFlowDTO request, User user) { - Map recreationMap = new HashMap<>(); - Map customRecreationMap = new HashMap<>(); - - request.getRecreationSpecList() - .forEach( - spec -> { - if (spec.getRecreationId() != null) { - Recreation recreation = - recreationRepository - .findById(spec.getRecreationId()) - .orElseThrow( - () -> - new RecreationException( - ErrorStatus - .RECREATION_NOT_FOUND)); - recreationMap.put(spec.getSeq(), recreation); - } else { - List customRecreationKeywordList = - new ArrayList<>(); - if (spec.getCustomKeywordList() != null) { - customRecreationKeywordList = - spec.getCustomKeywordList().stream() - .map( - keyword -> - recreationKeywordRepository - .findByKeyword(keyword) - .get()) - .toList(); - } - - CustomRecreation customRecreation = - FlowConverter.toCustomRecreation( - spec, customRecreationKeywordList); - - customRecreationRepository.save(customRecreation); - customRecreationMap.put(spec.getSeq(), customRecreation); - } - }); + Map recreationMap = extractRecreationMap(request); + Map customRecreationMap = extractCustomRecreationMap(request); List recreationKeywordList = - request.getKeywordList().stream() - .map(keyword -> recreationKeywordRepository.findByKeyword(keyword).get()) - .toList(); - + getRecreationKeywords(request.getKeywordList()); List recreationPurposeList = - request.getPurposeList().stream() - .map(purpose -> recreationPurposeRepository.findByPurpose(purpose).get()) - .toList(); - - int num = flowNumber.nextInt(4); - Flow flow = - FlowConverter.toFlow( - request, - user, - flowImageUrl[num], - recreationMap, - customRecreationMap, - recreationKeywordList, - recreationPurposeList); - - flowRepository.save(flow); - - return flow; + getRecreationPurposes(request.getPurposeList()); + + return createOrUpdateFlow( + request, + user, + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList, + null); } @Transactional public void deleteFlow(Long flowId, User user) { - Flow flow = - flowRepository - .findById(flowId) - .orElseThrow(() -> new FlowException(ErrorStatus.FLOW_NOT_FOUND)); + Flow flow = getFlow(flowId); if (!flow.isAuthoredBy(user)) { throw new FlowException(ErrorStatus.FLOW_DELETE_UNAUTHORIZED); } @@ -259,10 +207,7 @@ public List recommendFlows( @Override @Transactional public Flow updateFlow(PostFlowDTO request, User user, Long flowId) { - Flow flow = - flowRepository - .findById(flowId) - .orElseThrow(() -> new FlowException(ErrorStatus.FLOW_NOT_FOUND)); + Flow flow = getFlow(flowId); // custom, ageList, purposeList, genderList, keywordList는 시작하자마자 삭제 (일단 모두 삭제로 구현) flowRecreationKeywordRepository.deleteAllByFlow(flow); @@ -271,68 +216,22 @@ public Flow updateFlow(PostFlowDTO request, User user, Long flowId) { flowAgeRepository.deleteAllByFlow(flow); flowRecreationRepository.deleteAllByFlow(flow); - Map recreationMap = new HashMap<>(); - Map customRecreationMap = new HashMap<>(); - - request.getRecreationSpecList() - .forEach( - spec -> { - if (spec.getRecreationId() != null) { - Recreation recreation = - recreationRepository - .findById(spec.getRecreationId()) - .orElseThrow( - () -> - new RecreationException( - ErrorStatus - .RECREATION_NOT_FOUND)); - recreationMap.put(spec.getSeq(), recreation); - } else { - List customRecreationKeywordList = - new ArrayList<>(); - if (spec.getCustomKeywordList() != null) { - customRecreationKeywordList = - spec.getCustomKeywordList().stream() - .map( - keyword -> - recreationKeywordRepository - .findByKeyword(keyword) - .get()) - .toList(); - } - - CustomRecreation customRecreation = - FlowConverter.toCustomRecreation( - spec, customRecreationKeywordList); - - customRecreationRepository.save(customRecreation); - customRecreationMap.put(spec.getSeq(), customRecreation); - } - }); + Map recreationMap = extractRecreationMap(request); + Map customRecreationMap = extractCustomRecreationMap(request); List recreationKeywordList = - request.getKeywordList().stream() - .map(keyword -> recreationKeywordRepository.findByKeyword(keyword).get()) - .toList(); - + getRecreationKeywords(request.getKeywordList()); List recreationPurposeList = - request.getPurposeList().stream() - .map(purpose -> recreationPurposeRepository.findByPurpose(purpose).get()) - .toList(); - - int num = flowNumber.nextInt(4); - Flow updateFlow = - FlowConverter.toUpdateFlow( - flowId, - request, - user, - flowImageUrl[num], - recreationMap, - customRecreationMap, - recreationKeywordList, - recreationPurposeList); - - return flowRepository.save(updateFlow); + getRecreationPurposes(request.getPurposeList()); + + return createOrUpdateFlow( + request, + user, + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList, + flowId); } @Override @@ -340,4 +239,92 @@ public Flow updateFlow(PostFlowDTO request, User user, Long flowId) { public void incrementViewCountLast7Days(Long flowId, Long viewCount) { flowRepository.updateViewCountLast7DaysById(flowId, viewCount); } + + private Map extractRecreationMap(PostFlowDTO request) { + Map recreationMap = new HashMap<>(); + + for (var spec : request.getRecreationSpecList()) { + if (spec.getRecreationId() != null) { + Recreation recreation = getRecreation(spec.getRecreationId()); + recreationMap.put(spec.getSeq(), recreation); + } + } + + return recreationMap; + } + + private Map extractCustomRecreationMap(PostFlowDTO request) { + Map customRecreationMap = new HashMap<>(); + + for (var spec : request.getRecreationSpecList()) { + if (spec.getRecreationId() == null) { + List keywords = new ArrayList<>(); + if (spec.getCustomKeywordList() != null) { + keywords = getRecreationKeywords(spec.getCustomKeywordList()); + } + CustomRecreation customRecreation = + FlowConverter.toCustomRecreation(spec, keywords); + customRecreationRepository.save(customRecreation); + customRecreationMap.put(spec.getSeq(), customRecreation); + } + } + return customRecreationMap; + } + + private Flow createOrUpdateFlow( + PostFlowDTO request, + User user, + Map recreationMap, + Map customRecreationMap, + List recreationKeywordList, + List recreationPurposeList, + @Nullable Long flowId) { + int num = flowNumber.nextInt(4); + + Flow flow = + (flowId == null) + ? FlowConverter.toFlow( + request, + user, + flowImageUrl[num], + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList) + : FlowConverter.toUpdateFlow( + flowId, + request, + user, + flowImageUrl[num], + recreationMap, + customRecreationMap, + recreationKeywordList, + recreationPurposeList); + + return flowRepository.save(flow); + } + + private Flow getFlow(Long flowId) { + return flowRepository + .findById(flowId) + .orElseThrow(() -> new FlowException(ErrorStatus.FLOW_NOT_FOUND)); + } + + private Recreation getRecreation(Long recreationId) { + return recreationRepository + .findById(recreationId) + .orElseThrow(() -> new RecreationException(ErrorStatus.RECREATION_NOT_FOUND)); + } + + private List getRecreationKeywords(List keywords) { + return keywords.stream() + .map(keyword -> recreationKeywordRepository.findByKeyword(keyword).get()) + .toList(); + } + + private List getRecreationPurposes(List purposes) { + return purposes.stream() + .map(purpose -> recreationPurposeRepository.findByPurpose(purpose).get()) + .toList(); + } }