현재 개발된 부분은
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를 사용해서 기능을 구현 할 수 있었다.