Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 물품 주문자들의 성별 및 나이대별 평균 별점 구현 #161

Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ public SecurityFilterChain filterChain(final HttpSecurity http) throws Exception
.requestMatchers(new AntPathRequestMatcher("/api/v1/login"),
new AntPathRequestMatcher("/api/v1/signup"),
new AntPathRequestMatcher("/api/v1/products/**"),
new AntPathRequestMatcher("/api/v1/rate/product/**"))
new AntPathRequestMatcher("/api/v1/rate/product/*"),
new AntPathRequestMatcher("/api/v1/rate/product/*/all"))
.permitAll()
.anyRequest().authenticated()
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.gugucon.shopping.auth.dto.MemberPrincipal;
import com.gugucon.shopping.rate.dto.request.RateCreateRequest;
import com.gugucon.shopping.rate.dto.response.GroupRateResponse;
import com.gugucon.shopping.rate.dto.response.RateDetailResponse;
import com.gugucon.shopping.rate.dto.response.RateResponse;
import com.gugucon.shopping.rate.service.RateService;
Expand All @@ -11,6 +12,8 @@
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/v1/rate")
@RequiredArgsConstructor
Expand Down Expand Up @@ -44,4 +47,10 @@ public RateResponse getCustomRate(@PathVariable final Long productId,
@AuthenticationPrincipal final MemberPrincipal principal) {
return rateService.getCustomRate(productId, principal);
}

@GetMapping("/product/{productId}/all")
@ResponseStatus(HttpStatus.OK)
public List<GroupRateResponse> getGroupRates(@PathVariable final Long productId) {
return rateService.getGroupRates(productId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package com.gugucon.shopping.rate.dto.response;

import com.gugucon.shopping.member.domain.vo.BirthYearRange;
import com.gugucon.shopping.member.domain.vo.Gender;
import com.gugucon.shopping.rate.repository.dto.GroupAverageRateDto;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

@Getter
@NoArgsConstructor(access = AccessLevel.PRIVATE)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
public class GroupRateResponse {

private Gender gender;
private BirthYearRange birthYearRange;
private RateResponse rate;

public static GroupRateResponse of(final GroupAverageRateDto groupAverageRateDto, final double averageRate) {
return new GroupRateResponse(groupAverageRateDto.getGender(),
groupAverageRateDto.getBirthYearRange(),
new RateResponse(groupAverageRateDto.getCount(), averageRate));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@
import com.gugucon.shopping.member.domain.vo.Gender;
import com.gugucon.shopping.rate.domain.entity.Rate;
import com.gugucon.shopping.rate.repository.dto.AverageRateDto;
import java.util.Optional;
import com.gugucon.shopping.rate.repository.dto.GroupAverageRateDto;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Optional;

@Repository
public interface RateRepository extends JpaRepository<Rate, Long> {

Expand All @@ -34,4 +37,10 @@ public interface RateRepository extends JpaRepository<Rate, Long> {
AverageRateDto findScoresByMemberGenderAndMemberBirthYear(final Long productId,
final Gender gender,
final BirthYearRange birthYearRange);

@Query("SELECT new com.gugucon.shopping.rate.repository.dto.GroupAverageRateDto" +
"(rs.gender, rs.birthYearRange, rs.count, rs.totalScore) " +
"FROM RateStat rs " +
"WHERE rs.productId = :productId")
List<GroupAverageRateDto> findAllGroupsOfMemberGenderAndMemberBirthYear(final Long productId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.gugucon.shopping.rate.repository.dto;

import com.gugucon.shopping.member.domain.vo.BirthYearRange;
import com.gugucon.shopping.member.domain.vo.Gender;
import lombok.Getter;

@Getter
public class GroupAverageRateDto {

private final Gender gender;
private final BirthYearRange birthYearRange;
private final Long count;
private final Long totalScore;

public GroupAverageRateDto(final Gender gender,
final BirthYearRange birthYearRange,
final Long count,
final Long totalScore) {
this.gender = gender;
this.birthYearRange = birthYearRange;
this.count = count;
this.totalScore = totalScore;
}
}
16 changes: 16 additions & 0 deletions src/main/java/com/gugucon/shopping/rate/service/RateService.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,19 @@
import com.gugucon.shopping.order.repository.OrderItemRepository;
import com.gugucon.shopping.rate.domain.entity.Rate;
import com.gugucon.shopping.rate.dto.request.RateCreateRequest;
import com.gugucon.shopping.rate.dto.response.GroupRateResponse;
import com.gugucon.shopping.rate.dto.response.RateDetailResponse;
import com.gugucon.shopping.rate.dto.response.RateResponse;
import com.gugucon.shopping.rate.repository.RateRepository;
import com.gugucon.shopping.rate.repository.dto.AverageRateDto;
import com.gugucon.shopping.rate.repository.dto.GroupAverageRateDto;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Comparator;
import java.util.List;

@Service
@Transactional(readOnly = true)
@RequiredArgsConstructor
Expand Down Expand Up @@ -74,10 +79,21 @@ public RateResponse getCustomRate(final Long productId, final MemberPrincipal pr
return new RateResponse(rates.getCount(), averageRate);
}

public List<GroupRateResponse> getGroupRates(final Long productId) {
return rateRepository.findAllGroupsOfMemberGenderAndMemberBirthYear(productId).stream()
.sorted(Comparator.comparing(o -> o.getBirthYearRange().getStartDate(), Comparator.reverseOrder()))
.map(rateDto -> GroupRateResponse.of(rateDto, calculateAverageOf(rateDto)))
.toList();
}

private double calculateAverageOf(final AverageRateDto averageRateDto) {
return roundDownAverage((double) averageRateDto.getTotalScore() / averageRateDto.getCount());
}

private double calculateAverageOf(final GroupAverageRateDto averageRateDto) {
return roundDownAverage((double) averageRateDto.getTotalScore() / averageRateDto.getCount());
}

private double roundDownAverage(final double average) {
return Math.floor(average * 100) / 100.0;
}
Expand Down
Loading
Loading