당근 마켓 프로젝트2

Ango·2023년 7월 4일
0

Project

목록 보기
3/16

❓ 문제점

현재 개발된 부분은
1. 유저 로그인 회원가입 및 인가 기능
2. 고객 문의기능
3. 상담원의 고객 문의에 대한 답변 기능

오늘은
상담에 대한 고객의 별점 부여 기능을 구현했다.

🔑 시도 && 해결 방법

@Builder
@AllArgsConstructor
@Getter
public class User extends AuditingEntity {

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

    @Column(unique = true)
    private String userId;
    @Column
    private String userPw;

    @Column(unique = true)
    private String nickname;

    @Enumerated
    @Column
    private UserGender gender;
    @Column(unique = true)
    private String email;

    @Column
    private Double temperature;

    @Setter
    @Column
    Double starFromCustomer = (double) 0;

    @Column
    @Enumerated(EnumType.STRING)
    @Setter
    private UserRoleEnum role;

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user", fetch = FetchType.LAZY)
    private List<Shop> shopList = new ArrayList<>();

    int cnt_reply=0;

    protected User() {
    }

    public Double updateRating(int rating) {
        double sum = this.starFromCustomer * this.cnt_reply;
        this.cnt_reply++;
        this.starFromCustomer = (sum+rating) / (this.cnt_reply) ;

        return this.starFromCustomer;
    }
}

유저 엔티티는 위와같이 구성되어 있고 UserRole이 USER일때는 고객이 상담에 대해 준 별점의 평균값인 starFromCustomer이 NULL 값으로 들어가 있지만 ADMIN 계정에 대해서는 초기에 0으로 초기화 해주었다.

관리자 계정은 미리 생성되어 있다는 시나리오이다.

아무튼 관리자 즉 상담원이 고객의 문의에 대한 답변을 남기면 "문의글을 작성한 "고객이 해당 답변에 대해 별점을 줄 수 있게했다.

서비스 단이 중요하니까 해당 코드만 보면


@Service
@Slf4j
@RequiredArgsConstructor
public class RatingByUserService {

    private final ReplyRepository replyRepository;
    @Transactional
    public RatingByUserResponse RatingToAgent(Long replyId, RatingByUserRequest request , UserDetailsImpl userDetails) {
        Reply reply = replyRepository.findById(replyId).orElseThrow(() ->
                new CustomException(ErrorCode.NO_REPLY)
        );
        log.info(reply.getUser().getUserId());

        if(!checkThisUserInquiryWrite(userDetails,reply)){
            throw new CustomException(ErrorCode.NO_WRITER_TO_INQUIRY);
        }

        Double rating_star_avg = reply.getUser().updateRating(request.rating_star());

        return new RatingByUserResponse(userDetails.getUsername(), rating_star_avg);
    }



    public boolean checkThisUserInquiryWrite(UserDetailsImpl userDetails, Reply reply){
        log.info(userDetails.getUsername());

        if(!reply.getInquiry().getUser().getUserId().equals(userDetails.getUsername())){
            return false;
        }
        return true;

    }
}

checkThisUserInquiryWrite 매서드에서 현재 평점을 주려는 유저가 해당글을 작성한 유저가 맞는지 판단한다.
그리고 맞다면 rating을 주고 평점을 받은 상담원의 평균 평점이 계산되는데
그 부분은 아래와 같다 .

	
    @Column
    Double starFromCustomer = (double) 0;
    int cnt_reply=0;
    
     public Double updateRating(int rating) {
        double sum = this.starFromCustomer * this.cnt_reply;
        this.cnt_reply++;
        this.starFromCustomer = (sum+rating) / (this.cnt_reply) ;

        return this.starFromCustomer;
    }

평점을 준 고객의 수인 cnt_reply를 현재 평균값에 곱해서 총 받은 별점 수를 구하고 1 증가시킨 cnt_reply로 rating을 더한 총 별점의 수를 나누어 준다.

테스트 결과는

이미 3점, 3점 ,4점을 주었어서 5점을 주니까 평균인 3.75가 정확히 나오고 있다.


DB에도 잘 반영이 된 모습 ㅎㅎ

💡 알게 된 점

필드에 평점값을 업데이트하는것은 어렵지 않았는데 평균을 구해야해서 평점을 받은 횟수를 어떤식으로 구현해야 할지 고민이 됐었다 . 하지만 @Column 어노테이션을 달지 않음으로해서 DB에 저장하지 않고 Entity의 데이터로만 존재하는 cnt_reply를 사용해서 기능을 구현 할 수 있었다.

profile
웹 벡엔드 개발자가 되어보자!

0개의 댓글

관련 채용 정보