Skip to content

Commit

Permalink
Merge branch 'develop' into feature/140
Browse files Browse the repository at this point in the history
  • Loading branch information
FaberJoo committed Dec 8, 2023
2 parents 14ca243 + da81904 commit fc4bd17
Show file tree
Hide file tree
Showing 20 changed files with 510 additions and 110 deletions.
47 changes: 47 additions & 0 deletions src/docs/asciidoc/index.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1431,3 +1431,50 @@ include::{snippets}/checkAttractionPoint/isCheck/response-body.adoc[]

.response-fields
include::{snippets}/checkAttractionPoint/isCheck/response-fields.adoc[]

=== 입덕포인트 수정
=== PATCH api/v1/attraction-points/:attractionPointId
.curl-request
include::{snippets}/patchAttractionPoint/success/curl-request.adoc[]

.http-request
include::{snippets}/patchAttractionPoint/success/http-request.adoc[]

.request-header
include::{snippets}/patchAttractionPoint/success/request-headers.adoc[]

.request-body
include::{snippets}/patchAttractionPoint/success/request-body.adoc[]

.request-fields
include::{snippets}/patchAttractionPoint/success/request-fields.adoc[]

=== 성공 시

.http-response
include::{snippets}/patchAttractionPoint/success/http-response.adoc[]

=== 실패 시

.http-response
include::{snippets}/patchAttractionPoint/fail/http-response.adoc[]

=== GET api/v1/attraction-points/animes/:animeId
.curl-request
include::{snippets}/getAttractionPointStats/success/curl-request.adoc[]

.http-request
include::{snippets}/getAttractionPointStats/success/http-request.adoc[]

.path-parameters
include::{snippets}/getAttractionPointStats/success/path-parameters.adoc[]

==== 성공시
.http-response
include::{snippets}/getAttractionPointStats/success/http-response.adoc[]

.response-body
include::{snippets}/getAttractionPointStats/success/response-body.adoc[]

.response-fields
include::{snippets}/getAttractionPointStats/success/response-fields.adoc[]
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package io.oduck.api.domain.attractionPoint.controller;

import io.oduck.api.domain.attractionPoint.dto.AttractionPointReqDto.*;
import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import io.oduck.api.domain.attractionPoint.service.AttractionPointService;
import io.oduck.api.global.security.auth.dto.AuthUser;
import io.oduck.api.global.security.auth.dto.LoginUser;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
Expand All @@ -25,6 +27,7 @@ public ResponseEntity<?> postAttractionPoint(
@LoginUser AuthUser user,
@RequestBody @Valid AttractionPointReq req){
//TODO: 입덕포인트 작성

attractionPointService.save(user.getId(), req);
return ResponseEntity.ok().build();
}
Expand All @@ -35,4 +38,20 @@ public ResponseEntity<?> getAttractionPoint(
@PathVariable("animeId") Long animeId){
return ResponseEntity.ok(attractionPointService.checkAttractionPoint(user.getId(), animeId));
}

@PatchMapping("/{attractionPointId}")
public ResponseEntity<?> patchAttractionPoint(
@LoginUser AuthUser user,
@PathVariable("attractionPointId") Long attractionPointId,
@RequestBody @Valid UpdateAttractionPoint req){
boolean update = attractionPointService.update(user.getId(), attractionPointId, req);
return ResponseEntity.status(update? HttpStatus.NO_CONTENT : HttpStatus.CONFLICT).build();
}

@GetMapping("/animes/{animeId}")
public ResponseEntity<?> getAttractionPointStats(
@PathVariable("animeId") Long animeId){
//TODO: 애니의 따른 입덕포인트 통계 가져오기
return ResponseEntity.ok(attractionPointService.getAttractionPointStats(animeId));
}
}
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
package io.oduck.api.domain.attractionPoint.dto;

import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.ArrayList;
import java.util.List;

public class AttractionPointReqDto {

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
@NoArgsConstructor
public static class AttractionPointReq{
private Long animeId;
@NotNull(message = "입덕포인트를 선택하세요.")
List<AttractionElement> attractionElements;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class UpdateAttractionPoint{
@NotNull(message = "입덕포인트를 선택하세요.")
AttractionElement attractionElement;
}

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package io.oduck.api.domain.attractionPoint.dto;

import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.Map;
import java.util.stream.Collectors;

@Getter
@Builder
public class AttractionPointResDto {
Expand All @@ -25,4 +30,16 @@ public static class IsAttractionPoint{
public static class CheckAttractionPoint{
private Boolean isAttractionPoint;
}

@Builder
@Getter
@NoArgsConstructor
@AllArgsConstructor
public static class AttractionPointStats{
private double drawing;
private double story;
private double music;
private double character;
private double voiceActor;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.oduck.api.domain.attractionPoint.repository;

import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import io.oduck.api.domain.attractionPoint.entity.AttractionPoint;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
Expand All @@ -8,7 +9,7 @@
import org.springframework.stereotype.Repository;

@Repository
public interface AttractionPointRepository extends JpaRepository<AttractionPoint, Long>{
public interface AttractionPointRepository extends JpaRepository<AttractionPoint, Long>, AttractionPointRepositoryCustom{
@Query("select ap from AttractionPoint ap "
+ "where ap.anime.id = :animeId "
+ "and ap.member.id = :memberId")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.oduck.api.domain.attractionPoint.repository;

import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import io.oduck.api.domain.member.dto.MemberDslDto.ProfileWithoutActivity;

import java.util.Optional;

public interface AttractionPointRepositoryCustom {
Long countElementByAnimeId(AttractionElement attractionElement, Long animeId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package io.oduck.api.domain.attractionPoint.repository;

import com.querydsl.jpa.impl.JPAQueryFactory;
import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;

import static io.oduck.api.domain.attractionPoint.entity.QAttractionPoint.attractionPoint;


@Slf4j
@Repository
@RequiredArgsConstructor
class AttractionPointRepositoryImpl implements AttractionPointRepositoryCustom {
private final JPAQueryFactory query;

@Override
public Long countElementByAnimeId(AttractionElement attractionElement, Long animeId) {
Long elementCount = query
.select(attractionPoint.attractionElement.count())
.from(attractionPoint)
.where(attractionPoint.attractionElement.eq(attractionElement)
.and(attractionPoint.anime.id.eq(animeId)))
.fetchOne();
return elementCount;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,8 @@ public interface AttractionPointService {

//입덕포인트 조회(true/false)
IsAttractionPoint isAttractionPoint(Long memberId, Long animeId);

boolean update(Long memberId, Long attractionPointId, UpdateAttractionPoint req);

AttractionPointStats getAttractionPointStats(Long anime);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@
import io.oduck.api.domain.anime.repository.AnimeRepository;
import io.oduck.api.domain.attractionPoint.dto.AttractionPointReqDto.*;
import io.oduck.api.domain.attractionPoint.dto.AttractionPointResDto.*;
import io.oduck.api.domain.attractionPoint.entity.AttractionElement;
import io.oduck.api.domain.attractionPoint.entity.AttractionPoint;
import io.oduck.api.domain.attractionPoint.repository.AttractionPointRepository;

import java.util.ArrayList;
import java.util.List;
import java.util.*;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import io.oduck.api.domain.member.entity.Member;
import io.oduck.api.domain.member.repository.MemberRepository;
import io.oduck.api.domain.review.entity.ShortReview;
import io.oduck.api.global.exception.BadRequestException;
import io.oduck.api.global.exception.ConflictException;
import io.oduck.api.global.exception.NotFoundException;
import lombok.RequiredArgsConstructor;
Expand Down Expand Up @@ -48,19 +51,32 @@ public IsAttractionPoint isAttractionPoint(Long memberId, Long animeId) {
}
}
return IsAttractionPoint
.builder()
.drawing(drawing)
.story(story)
.music(music)
.character(character)
.voiceActor(voiceActor)
.build();
.builder()
.drawing(drawing)
.story(story)
.music(music)
.character(character)
.voiceActor(voiceActor)
.build();
}

@Override
@Transactional
public void save(Long memberId, AttractionPointReq req) {
if(checkAttractionPoint(memberId, req.getAnimeId()).getIsAttractionPoint()){
List<AttractionPoint> findPoint = attractionPointRepository.findAllByAnimeIdAndMemberId(memberId, req.getAnimeId());

List<AttractionElement> elementList = findPoint.stream()
.map(AttractionPoint::getAttractionElement)
.toList();

//중복되지 않은 포인트
List<AttractionElement> matchPoint = req.getAttractionElements().stream()
.filter(attractionElements ->
elementList.stream()
.noneMatch(Predicate.isEqual(attractionElements)))
.toList();

if (matchPoint.isEmpty()) {
throw new ConflictException("AttractionPoint");
}

Expand All @@ -70,15 +86,15 @@ public void save(Long memberId, AttractionPointReq req) {
Anime anime = animeRepository.findById(req.getAnimeId())
.orElseThrow(() -> new NotFoundException("Anime"));

List<AttractionPoint> points = req.getAttractionElements()
List<AttractionPoint> points = matchPoint
.stream()
.map(attractionElement -> AttractionPoint
.builder()
.member(member)
.anime(anime)
.attractionElement(attractionElement)
.build())
.toList();
.toList();
attractionPointRepository.saveAll(points);
}

Expand All @@ -90,4 +106,62 @@ public CheckAttractionPoint checkAttractionPoint(Long memberId, Long animeId) {
.isAttractionPoint(!findPoint.isEmpty())
.build();
}

@Override
public boolean update(Long memberId, Long attractionPointId, UpdateAttractionPoint req) {
AttractionPoint findAttractionPoint = getAttractionPoint(attractionPointId);

if (findAttractionPoint.getAttractionElement().equals(req.getAttractionElement())) {
return false;
}
Long findMemberId = findAttractionPoint.getMember().getId();
//입덕 포인트 작성자 인지 확인
Optional
.ofNullable(findMemberId)
.ifPresent(
id -> {
if (!findMemberId.equals(memberId)) {
throw new BadRequestException("Not the author of the attractionPoint.");
}
findAttractionPoint.updateElement(req.getAttractionElement());
}
);
attractionPointRepository.save(findAttractionPoint);
return true;
}

@Override
public AttractionPointStats getAttractionPointStats(Long animeId) {
//입덕포인트 / 전체 입덕포인트 개수
Long totalCount = attractionPointRepository.count();
double drawing = calculateElementRatio(AttractionElement.DRAWING, animeId, totalCount);
double story = calculateElementRatio(AttractionElement.STORY, animeId, totalCount);
double voiceActor = calculateElementRatio(AttractionElement.VOICE_ACTOR, animeId, totalCount);
double music = calculateElementRatio(AttractionElement.MUSIC, animeId, totalCount);
double character = calculateElementRatio(AttractionElement.CHARACTER, animeId, totalCount);

return AttractionPointStats.builder()
.drawing(drawing)
.voiceActor(voiceActor)
.story(story)
.music(music)
.character(character)
.build();
}

private AttractionPoint getAttractionPoint(Long attractionPointId) {
return attractionPointRepository.findById(attractionPointId)
.orElseThrow(
() -> new NotFoundException("AttractionPoint")
);
}

private double calculateElementRatio(AttractionElement element, Long animeId, Long totalCount) {
Long countElementByAnimeId = attractionPointRepository.countElementByAnimeId(element, animeId);
if (countElementByAnimeId <= 0) {
return 0;
}
return (double) countElementByAnimeId / totalCount;
}

}
Loading

0 comments on commit fc4bd17

Please sign in to comment.