def picks(self, request, pk=None): """ 회원 프로필에서 캐스트(픽) 리스트 --- - 마지막 항번값으로 페이징 처리를 합니다. 첫 페이지 호출할때 last_key 값을 넘기지 않아야 합니다. - 회원 프로필에서는 캐스트(픽) 카테고리 정보에 'is_new' 정보는 항상 없습니다. """ response = {} get_object_or_404(User, id=pk) params = UserPicksForm(data=request.GET) params.is_valid(raise_exception=True) cursor = params.validated_data.get('cursor') if cursor is None: response['categories'] = pick_service.get_user_pick_categories(user_id=pk) picks, total_count, next_offset = pick_service.get_user_picks(user_id=pk, **params.validated_data) response['picks'] = picks response['paging'] = dict() if total_count: response['total_count'] = total_count if next_offset: response['paging']['next'] = next_offset return Response(PickListResponse(response).data)
def edit(self, request, pk=None): """ 제품 수정 요청 """ params = RequestForm(data=request.data) params.is_valid(raise_exception=True) user_id = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=user_id) product = get_object_or_404(Product, id=pk) contents = params.validated_data.get('contents') now = local_now().strftime('%Y%m%d%H%M%S') response = dict() try: RequestedEditProduct(contents=contents, product=product, user=user, create_date=now).save() response['is_success'] = True response['message'] = _("소중한 정보 감사합니다! 빠르게 수정하겠습니다:)") except: response['is_success'] = False response['message'] = _("요청 등록에 실패하였습니다.") return Response(SuccessMessageResponse(response).data, status=status.HTTP_201_CREATED)
def ingredient(self, request, pk=None): """ 성분등록요청 --- 'file' 키값으로 이미지 파일 전송 <br><br> 헤더 <br> - IDREGISTER: (필수) 회원 항번 <br> """ user_id = request.META.get('HTTP_IDREGISTER') file_obj = request.FILES.get('file') user = get_object_or_404(User, id=user_id) product = get_object_or_404(Product, id=pk) now = local_now().strftime('%Y%m%d%H%M%S') response = dict() try: if file_obj: if RequestedIngredient.objects.filter( user=user, product=product).exists(): response['is_success'] = False response['message'] = _("이미 성분등록 요청을 하셨습니다.") return Response(SuccessMessageResponse(response).data, status=status.HTTP_201_CREATED) requested_ingredient = RequestedIngredient(user=user, product=product, create_date=now) requested_ingredient.save() file_info = store_requested_ingredient_image( file_obj, requested_ingredient.id) if file_info: requested_ingredient.file_name_orig = file_info.get( 'file_org_name') requested_ingredient.file_name_save = file_info.get( 'file_save_name') requested_ingredient.file_dir = file_info.get('file_dir') requested_ingredient.file_size = file_info.get('file_size') requested_ingredient.file_type = file_info.get('file_type') requested_ingredient.save() response['is_success'] = True response['message'] = _("성분요청이 정상적으로 등록되었습니다.") else: response['is_success'] = False response['message'] = _("성분요청시 성분이미지는 필수 입니다.") except: response['is_success'] = False response['message'] = _("요청 등록에 실패하였습니다.") return Response(SuccessMessageResponse(response).data, status=status.HTTP_201_CREATED)
def wish(self, request, pk=None): """ 위시 확인 / 추가 / 삭제 --- - IDREGISTER: (필수) 회원 항번 <br> """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=cuid) product = get_object_or_404(Product, id=pk) response = dict() if request.method == 'GET': if Wish.objects.filter(user=user, product=product).exists(): response['is_success'] = False response['message'] = _("이미 위시리스트에 있습니다.") else: response['is_success'] = True response['message'] = _("위시리스트에 추가할 수 있습니다.") elif request.method == 'POST': if Wish.objects.filter(user=user, product=product).exists(): response['is_success'] = False response['message'] = _("이미 위시리스트에 있습니다.") else: try: now = local_now().strftime('%Y%m%d%H%M%S') Wish(user=user, product=product, create_date=now).save() response['is_success'] = True msg_arr = [ _("지름신 팍팍! 위시리스트 등록 완료"), _("코덕으로 가는 지름길! 위시리스트 등록 완료~") ] response['message'] = random.choice(msg_arr) except: response['is_success'] = False response['message'] = _("추가에 실패하였습니다.") elif request.method == 'DELETE': qs = Wish.objects.filter(user=user, product=product) if qs.exists(): qs.delete() response['is_success'] = True response['message'] = _("위시리스트가 삭제되었습니다.") else: response['is_success'] = False response['message'] = _("이미 삭제되었습니다.") return Response( SuccessMessageResponse(response).data, status=status.HTTP_200_OK )
def check(self, request, pk=None): """ 알림함 메세지 체크 --- """ user_id = self.request.META.get('HTTP_IDREGISTER') user = get_object_or_404(User, id=user_id) message = get_object_or_404(MessageBox, id=pk) obj, created = MessageCheck.objects.get_or_create(user=user, message=message) obj.read_at = utc_now() obj.save() return Response(MessageReadSerializer(obj).data, status=status.HTTP_200_OK)
def count(self, request): """ 알림함 뱃지 카운트 --- """ # 14일 지난 메세지 삭제 처리 last_created_at = utc_now() - timedelta(days=14) user_id = self.request.META.get('HTTP_IDREGISTER') if user_id is None or user_id == '0': return Response({'count': 0}, status=status.HTTP_200_OK) MessageBox.objects.filter( Q(user_id=user_id) | Q(user_id__isnull=True, group_id__isnull=True)).filter( updated_at__lt=last_created_at, is_active=True).update(is_active=False) user = get_object_or_404(User, id=user_id) joined_at = user.date_joined - timedelta(hours=9) query_set = MessageBox.objects.filter( Q(user_id=user_id) | Q(user_id__isnull=True, group_id__isnull=True)).filter( created_at__range=(joined_at, utc_now()), is_active=True).distinct() count = query_set.exclude(messagecheck__user_id=user_id).count() return Response({'count': count}, status=status.HTTP_200_OK)
def reports(self, request, pk=None): """ 리뷰 신고 --- 헤더 값 <br> IDREGISTER (필수) """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) params = ReviewReportForm(data=request.data) params.is_valid(raise_exception=True) client_ip = get_client_ip(request) report_type = params.validated_data.get('report_type') contents = params.validated_data.get('contents') review = get_object_or_404(Review, id=pk) if cuid == review.user_id: raise InvalidParameterException() if review_service.has_report(pk, cuid): raise ConflictException( _("이미 신고한 리뷰입니다.") ) review_service.create_report(pk, cuid, client_ip, report_type, contents, review.user_id) # 리뷰 신고 카운트 증가 review.report_count += 1 review.save() return Response({}, status=status.HTTP_201_CREATED)
def retrieve(self, request, pk=None): """ 어워드 수상 제품 전체 """ try: results = awards_service.get_awards_products_by_dynamodb( award_id=pk) except: get_object_or_404(Awards, id=pk) results = awards_service.get_award_products(award_id=pk) response = dict() response['awards'] = results return Response(AwardsCategoryProductsResponse(response).data, status=status.HTTP_200_OK)
def retrieve(self, request, pk=None): """ 제품 상세 정보 """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) product = get_object_or_404(Product, id=pk) product.read_count += 1 product.save() response = dict() ads_id = None try: response['product'] = products_service.get_product_detail_dynamodb(product.id) month_new = response['product'].get('month_new') if month_new: ads_id = month_new.get('id') except: response['product'] = products_service.get_product_detail(product) month_new = getattr(response['product'], 'month_new') if month_new: ads_id = month_new.id # ads server if ads_id: request_ads('GP0010', str(ads_id)) if cuid > 0: user = User.objects.get(id=cuid) response['is_wish'] = user.wishes.filter(id=pk).exists() if (user._gender is None) or (user._skin_type is None): response['is_review_type'] = 'more' response['is_review_message'] = _("내정보에서 추가정보를 입력하셔야 작성이 가능합니다.") elif Review.objects.filter(user=user, product=product).exists(): response['is_review_type'] = 'wrote' response['is_review_message'] = _("이미 리뷰를 작성한 제품입니다:(\n다른 제품에도 솔직평가 남겨주세요!") response['my_review'] = Review.objects.get(user=user, product=product) else: response['is_review_type'] = 'ok' else: response['is_wish'] = False response['is_review_type'] = "join" response['is_review_message'] = _("회원가입이 필요합니다.") qs = Review.objects.filter( product=pk, is_display=True, state='N', user__is_blinded=0 ) rating_avg = qs.aggregate(Avg('rating')) if isinstance(response['product'], dict): response['product']['rating_avg'] = round(float(rating_avg.get('rating__avg') or 0), 2) response['product']['review_count'] = qs.count() else: setattr(response['product'], 'rating_avg', round(float(rating_avg.get('rating__avg') or 0), 2)) setattr(response['product'], 'review_count', qs.count()) return Response(ProductDetailResponse(response).data, status=status.HTTP_200_OK)
def guide_ingredient(self, product_id): """ 제품 성분 가이드 높은 위험도 - C05 중간 위험도 - C04 낮은 위험도 - C03 성분 미정 - C02 성분정보 없음 - C01 """ ingredient_guide = {'case': 'C01'} product = get_object_or_404(Product, id=product_id) if not product.factors_display: return ingredient_guide ingredients = Ingredient.objects.filter( productingredient__product=product_id) undefined_ingredients = list( filter(lambda x: x.ewg_min is None, ingredients)) if undefined_ingredients: # 성분 미정 ingredient_guide['case'] = 'C02' ingredient_guide['undefined_count'] = len(undefined_ingredients) noxious_ingredients = list( filter( lambda x: (x.ewg_min is not None and x.ewg_min > 6) or (x.ewg_max is not None and x.ewg_max > 6), ingredients)) if noxious_ingredients: # 7-10 등급의 성분이 1개 이상인 경우 ingredient_guide['case'] = 'C05' ingredient = noxious_ingredients.pop(0) ingredient_guide[ 'noxious_ingredient_name'] = ingredient.korean_name if noxious_ingredients: ingredient_guide['noxious_ingredient_count'] = len( noxious_ingredients) else: intermediate_risk_ingredients = list( filter( lambda x: (x.ewg_min is not None and x.ewg_min > 2) or (x.ewg_max is not None and x.ewg_max > 2), ingredients)) if intermediate_risk_ingredients: # 3-6 등급의 성분이 포함된 경우 ingredient_guide['case'] = 'C04' else: safe_ingredients = list( filter( lambda x: (x.ewg_min is not None and x.ewg_min >= 0) or (x.ewg_min is not None and x.ewg_min >= 0), ingredients)) if safe_ingredients: # 0-2 등급의 성분으로만 구성된 경우 ingredient_guide['case'] = 'C03' return ingredient_guide
def create(self, request, pick_id=None): """ 픽 (캐스트) 댓글 추가 --- <br> <b>헤더</b> - IDREGISTER: (필수) 회원 항번 <br> """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=cuid) pick = get_object_or_404(Pick, pick_id=pick_id) params = PickCommentForm(data=request.data) params.is_valid(raise_exception=True) if not (user.gender and user.skin_type and user.birth_year): raise InvalidParameterException( _("프로필 편집에서 추가정보를 입력하셔야 참여가 가능합니다.") ) response = dict() try: with transaction.atomic(): PickComment( pick=pick, user=user, comment=params.validated_data.get('comment'), ip_address=get_client_ip(request), create_date=local_now().strftime('%Y%m%d%H%M%S') ).save() # 픽상세 뷰용 업데이트 aws_dynamodb_pick.update_comment_count( pick_id=pick_id, comment_count=PickComment.objects.filter(pick=pick_id, is_display=True).count() + 1 ) response['is_success'] = True response['message'] = _("댓글 등록 완료!") except: response['is_success'] = False response['message'] = _("등록에 실패하였습니다.") return Response( SuccessMessageResponse(response).data, status=status.HTTP_201_CREATED )
def report_types(self, request): """ 리뷰 신고 유형 목록 --- """ type = 'review_report_type_cd' common_code = get_object_or_404(CommonCode, code_value=type) return Response( ReportTypesResponse({"report_types": review_service.get_report_types(common_code)}).data, status=status.HTTP_200_OK )
def wishes(self, request, pk=None): """ 회원 프로필에서 위시 리스트 """ get_object_or_404(User, id=pk) params = UserProductsForm(data=request.GET) params.is_valid(raise_exception=True) cursor = params.validated_data.get('cursor') response = dict() response['products'], next_offset = wish_service.get_list(pk, **params.validated_data) if cursor is None: response['total_count'] = wish_service.get_list(pk, only_count=True, **params.validated_data) response['paging'] = dict() if next_offset: response['paging']['next'] = next_offset return Response(UserWishesResponse(response).data)
def post(self, request): """ service - ec 간 유저 모델 동기화 처리 """ user_id = request.POST.get('user_id') user = get_object_or_404(User, id=user_id) try: obj, created = EcUser.objects.get_or_create(id=user.id) for field in user._meta.fields: setattr(obj, field.name, getattr(user, field.name)) obj.save() except Exception as err: logger.error(str(err)) return Response(status=status.HTTP_204_NO_CONTENT)
def get_queryset(self): user_id = self.request.META.get('HTTP_IDREGISTER') user = get_object_or_404(User, id=user_id) joined_at = user.date_joined - timedelta(hours=9) query_set = super(MessageView, self).get_queryset() query_set = query_set.select_related('category').filter( created_at__range=(joined_at, utc_now())).filter( Q(user_id=user_id) | Q(user_id__isnull=True, group_id__isnull=True)).exclude( messagecheck__in=MessageCheck.objects.filter( user=user, deleted_at__isnull=False)).distinct() return query_set
def detail(self, request, pk=None): """ 제품 상세 정보 """ product = get_object_or_404(Product, id=pk) product.read_count += 1 product.save() response = dict() try: res = products_service.get_product_detail_dynamodb(product.id) response['product'] = ProductDetail(res).data except: response['product'] = ProductDetail(product).data return Response(response, status=status.HTTP_200_OK)
def products(self, request, pk=None): """ 카테고리별 제품 순위 리스트 """ category = get_object_or_404(SubCategory, id=pk) params = CategoryProductsForm(data=request.GET) params.is_valid(raise_exception=True) cursor = params.validated_data.get('cursor') response = dict() results = ranking_service.get_products_ranking_by_category_id( category_id=pk, **params.validated_data) response['products'] = results.get('list') response['paging'] = dict() next_offset = results.get('next_offset') if next_offset: response['paging']['next'] = next_offset if cursor is None: response['category_info'] = category products_count = results.get('products_count') if products_count: response['total_count'] = products_count recommend_product = ranking_service.get_recommend_product_by_sub_category_id( category_id=pk) if recommend_product: response['recommend_products'] = [recommend_product] # ads server ad_type = recommend_product.get('product_type') if ad_type == 'like': request_ads('GP0009', str(recommend_product.get('id'))) elif ad_type == 'editor': request_ads('GP0012', str(recommend_product.get('product_id'))) return Response(CategoryProductsResponse(response).data, status=status.HTTP_200_OK)
def ingredients(self, request, pk=None): """ 제품 성분 리스트 """ product = get_object_or_404(Product, id=pk) ingredients = Ingredient.objects.filter( productingredient__product=pk ).order_by( 'productingredient__seq' ) response = dict() response['product'] = product response['ingredients'] = ingredients return Response( ProductIngredientsResponse(response).data, status=status.HTTP_200_OK )
def can_report(self, request, pk=None): """ 리뷰 신고 확인 --- 헤더 값 <br> IDREGISTER (필수) """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) review = get_object_or_404(Review, id=pk) if cuid == review.user_id: raise InvalidParameterException() if review_service.has_report(pk, cuid): raise ConflictException( _("이미 신고한 리뷰입니다.") ) return Response({}, status=status.HTTP_200_OK)
def reviews(self, request, pk=None): """ 회원 프로필에서 리뷰 리스트 """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=pk) params = UserReviewsForm(data=request.GET) params.is_valid(raise_exception=True) cursor = params.validated_data.get('cursor') response = dict() review_service.setter(user_id=pk) results = review_service.get_list( request_user_id=cuid, user_id=user.id, **params.validated_data) reviews = list(results['list'] or []) response['reviews'] = reviews if cursor is None: response['total_count'] = review_service.get_list( only_count=True, request_user_id=cuid, user_id=user.id, **params.validated_data ) like_count = results.get('like_count') if like_count is not None: response['like_count'] = results.get('like_count') response['paging'] = dict() next_offset = results.get('next_offset') if next_offset: response['paging']['next'] = next_offset return Response(UserReviewsResponse(response).data, status=status.HTTP_200_OK)
def check(self, request): """ 리뷰 작성 확인 --- 헤더 값 <br> IDREGISTER (필수) """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) if not cuid > 0: raise InvalidParameterException( _("로그인이 필요합니다.") ) params = ReviewCheckForm(data=request.GET) params.is_valid(raise_exception=True) product_id = params.validated_data.get('product_id') response = dict() product = get_object_or_404(Product, id=product_id) response['product'] = product try: review = Review.objects.get(user_id=cuid, product=product) blinded_causes = blinded_review_service.get(review.id) setattr(review, 'blinded_causes', [OrderedDict( {'cause': item.cause.cause, 'guide': item.cause.guide}) for item in blinded_causes]) response['is_comment'] = True response['review'] = review response['message'] = _("이미 리뷰를 작성한 제품입니다.\n수정하시겠어요?") except Review.DoesNotExist: response['is_comment'] = False return Response(ReivewCheckResponse(response).data, status=status.HTTP_200_OK)
def profile(self, request, pk=None): user = get_object_or_404(User, id=pk) response = dict() if request.method == 'GET': response = UserProfileResponse(user) return Response(response.data, status=status.HTTP_200_OK) elif request.method == 'PUT': name = request.POST.get('name') contact = request.POST.get('contact') zipcode = request.POST.get('zip') address = request.POST.get('address') address_more = request.POST.get('address_more') user.name = name user.tel = contact user.zipcode = zipcode user.address = address user.address_more = address_more user.save() return Response(response, status=status.HTTP_200_OK)
def list(self, request, *args, **kwargs): """ 알림 메세지 리스트 --- <b>헤더</b> - IDREGISTER: (필수) 회원 항번 <br> """ user_id = self.request.META.get('HTTP_IDREGISTER') user = get_object_or_404(User, id=user_id) response = super(MessageView, self).list(request, *args, **kwargs) query_set = self.get_queryset() latest_checked_at = utc_now() - timedelta(days=14) query_set = query_set.exclude(id__in=[ checked.message_id for checked in MessageCheck.objects.filter( user=user, checked_at__gte=latest_checked_at) ]) MessageCheck.objects.bulk_create([ MessageCheck(user=user, message=message) for message in query_set ]) return response
def create(self, request): """ 새 리뷰 작성 --- <br> <b>헤더</b> - IDREGISTER: (필수) 회원 항번 <br> """ # parameters cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=cuid) review_service.reset_rank(cuid) params = ReviewWriteForm(data=request.data) params.is_valid(raise_exception=True) if user.gender is None or user.skin_type is None or user.birth_year is None: raise InvalidParameterException( _("내정보에서 추가정보를 입력하셔야 작성이 가능합니다.") ) client_ip = get_client_ip(request) contents = params.validated_data.get('contents') rating = params.validated_data.get('rating') product_id = params.validated_data.get('product_id') product = get_object_or_404(Product, id=product_id, is_display=True) if Review.objects.filter(user=cuid, product=product_id).exists(): raise ConflictException( _("이미 리뷰를 작성한 제품입니다.") ) with transaction.atomic(): # review insert now = local_now().strftime('%Y%m%d%H%M%S') review = Review(user=user, product=product, rating=rating, contents=contents, ip_address=client_ip, is_display=True, is_evaluation=False, _created_at=now) # 평가단 여부 확인 if EventPrizeMapping.objects.filter( user=user, product=product ).filter( event__activity_date__gte=local_now().strftime('%Y%m%d%H%M%S') ).exists(): review.is_evaluation = True review.save() # user info update user.review_count += 1 user.score += 1 user.save() # product info update update_product_info.delay(product_id) # tag update tags = extract_tags(contents) for tag_name in tags: tag, created = Tag.objects.get_or_create(name=tag_name) if created: TagObject(type='review', object_id=review.id, tag=tag).save() tag.create_date = now tag.save() else: if not TagObject.objects.filter(type='review', object_id=review.id, tag=tag).exists(): TagObject(type='review', object_id=review.id, tag=tag).save() tag.count += 1 tag.modified_date = now tag.save() review.tag = ",".join(tags) review.save() # elastic update body = dict() # review body['idreviewcomment'] = review.id body['reviewText'] = contents body['rating'] = rating body['likeCount'] = 0 body['isDisplay'] = 1 body['isEvaluation'] = 0 body['create_date'] = now body['tag'] = ",".join(tags) # user body['idRegister'] = user.id body['nickName'] = user.nickname body['birthYear'] = user.birth_year body['skinType'] = user._skin_type body['gender'] = user._gender body['registerScore'] = user.score body['registerRank'] = user.rank body['isBlind'] = user.is_blinded body['registerFileDir'] = user.file_dir body['registerFileSaveName'] = user.file_name_save # product body['idProduct'] = product.id body['productTitle'] = product.name body['idBrand'] = product.brand_id body['productFileDir'] = product.file_dir body['productFileSaveName'] = product.file_name body['brandTitle'] = product.brand.name body['productIsDisplay'] = int(product.is_display) categories = product.categories.all().values('id', 'main_category_id') body['firstCategoryList'] = "" body['secondCategoryList'] = "" for category in categories: body['firstCategoryList'] += "[" + str(category['main_category_id']) + "]" body['secondCategoryList'] += "[" + str(category['id']) + "]" try: goods_info = ProductGoods.objects.get(product_id=product_id, goods_count__gt=0) body['goods_info'] = { "goods_count": goods_info.goods_count, "min_price": goods_info.min_price, "max_price": goods_info.max_price } except ProductGoods.DoesNotExist: pass elasticsearch_reviews.add(body=body, _id=review.id) is_first = not Review.objects.filter(product=product_id).exists() response = dict() response['review_count'] = user.review_set.count() # redis 에 update 하는 쿼리 # 첫 번째 리뷰인지 확인한다. # 첫 리뷰시에 첫 리뷰 관리 테이블에 넣는다. if (is_first): try: Review_first_log(id=product_id, user=user, timestamp=kst_now().strftime("%Y%m%d%H%M%S") ).save(force_insert=True) except IntegrityError : # 테이블에 접근하는 순간 이미 product 가 존재해서 에러를 띄운다면 처음이 아님으로 is_first 를 False 로 변경한다. is_first = False review_create_cash = { 'is_first':is_first, 'written':True } # review count 에서 사용할 수 있도록 redis 에 set 해준다. set_review_is_written(user.id,review_create_cash) return Response(ReviewWriteResponse(response).data, status=status.HTTP_201_CREATED)
def update_product_info(product_id): """ 제품에 작성된 리뷰를 가지고 점수를 계산한다. """ # product score update product = get_object_or_404(Product, id=product_id, is_display=True) reviews = Review.objects.filter(product=product, is_display=True, state='N', user__is_blinded=0) result = reviews.annotate( rating1=Case(When(rating=1, then=1), output_field=IntegerField(), default=0), rating2=Case(When(rating=2, then=1), output_field=IntegerField(), default=0), rating3=Case(When(rating=3, then=1), output_field=IntegerField(), default=0), rating4_1=Case( When(Q(rating=4, user__review_count__lte=1), then=1), output_field=IntegerField(), default=0 ), rating4_2=Case( When(Q(rating=4, user__review_count__gt=1, user__review_count__lte=10), then=1), output_field=IntegerField(), default=0 ), rating4_3=Case( When(Q(rating=4, user__review_count__gt=10, user__review_count__lt=30), then=1), output_field=IntegerField(), default=0 ), rating4_4=Case( When(Q(rating=4, user__review_count__gte=30), then=1), output_field=IntegerField(), default=0 ), rating5_1=Case( When(Q(rating=5, user__review_count__lte=1), then=1), output_field=IntegerField(), default=0 ), rating5_2=Case( When(Q(rating=5, user__review_count__gt=1, user__review_count__lte=10), then=1), output_field=IntegerField(), default=0 ), rating5_3=Case( When(Q(rating=5, user__review_count__gt=10, user__review_count__lt=30), then=1), output_field=IntegerField(), default=0 ), rating5_4=Case( When(Q(rating=5, user__review_count__gte=30), then=1), output_field=IntegerField(), default=0 ), ).aggregate( Sum('rating1'), Sum('rating2'), Sum('rating3'), Sum('rating4_1'), Sum('rating4_2'), Sum('rating4_3'), Sum('rating4_4'), Sum('rating5_1'), Sum('rating5_2'), Sum('rating5_3'), Sum('rating5_4') ) rating1 = result['rating1__sum'] rating2 = result['rating2__sum'] rating3 = result['rating3__sum'] rating4_1 = result['rating4_1__sum'] rating4_2 = result['rating4_2__sum'] rating4_3 = result['rating4_3__sum'] rating4_4 = result['rating4_4__sum'] rating5_1 = result['rating5_1__sum'] rating5_2 = result['rating5_2__sum'] rating5_3 = result['rating5_3__sum'] rating5_4 = result['rating5_4__sum'] # review count review_count = rating1 + rating2 + rating3 + \ rating4_1 + rating4_2 + rating4_3 + rating4_4 + \ rating5_1 + rating5_2 + rating5_3 + rating5_4 # rating_avg rating_avg = (rating1 * 1.0 + rating2 * 2.0 + rating3 * 3.0 + ( rating4_1 + rating4_2 + rating4_3 + rating4_4) * 4.0 + ( rating5_1 + rating5_2 + rating5_3 + rating5_4) * 5) / review_count rating_avg = round(rating_avg, 2) # product score converted_sum = rating1 * -20.0 + rating2 * -10.0 + rating3 * -1.0 converted_sum += rating4_1 * 0.5 + rating4_2 * 2.5 + rating4_3 * 4.0 + rating4_4 * 5.0 converted_sum += rating5_1 * 1.0 + rating5_2 * 5.0 + rating5_3 * 8.0 + rating5_4 * 10.0 if review_count > 70: score = converted_sum / review_count * 70 else: score = converted_sum review_count_score = review_count * 0.05 if review_count * 0.05 <= 50.0 else 50.0 score += review_count_score score = round(score, 2) product.score = score product.review_count = review_count product.rating_avg = rating_avg product.save() # dynamo update attr_update = {'rating_avg': {'Value': {'N': str(product.rating_avg)}, 'Action': 'PUT'}, 'review_count': {'Value': {'N': str(product.review_count)}, 'Action': 'PUT'}} aws_dynamodb_products.update(product_id, attr_update) return product_id
def update(self, request, pk=None): """ 리뷰 수정 --- <br> <b>헤더</b> - IDREGISTER: (필수) 회원 항번 <br> """ # parameters cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=cuid) params = ReviewUpdateForm(data=request.data) params.is_valid(raise_exception=True) client_ip = get_client_ip(request) contents = params.validated_data.get('contents') new_rating = params.validated_data.get('rating') review = get_object_or_404(Review, id=pk, user=user, is_display=True) product = review.product with transaction.atomic(): # review update # 블라인드 상태인 리뷰는 사용자가 수정시 검수중 상태로 변경된다. if review.state == 'B': review.state = 'C' review.ip_address = client_ip if contents: review.contents = contents if new_rating: review.rating = new_rating review.save() # product info update update_product_info.delay(product.id) # tag update tags = extract_tags(contents) now = local_now().strftime('%Y%m%d%H%M%S') object_tags = TagObject.objects.filter(type='review', object_id=review.id) # tag count update for _obj in object_tags: _obj.tag.count -= 1 _obj.tag.modified_date = now _obj.tag.save() # delete tag mapping if object_tags.exists(): object_tags.delete() for tag_name in tags: tag, created = Tag.objects.get_or_create(name=tag_name) if created: TagObject(type='review', object_id=review.id, tag=tag).save() tag.create_date = now tag.save() else: if not TagObject.objects.filter(type='review', object_id=review.id, tag=tag).exists(): TagObject(type='review', object_id=review.id, tag=tag).save() tag.count += 1 tag.modified_date = now tag.save() review.tag = ",".join(tags) # review update review.save() # elastic update body = { "doc": {'rating': new_rating, 'reviewText': contents, 'tag': ",".join(tags)} } elasticsearch_reviews.update(_id=review.id, body=body) return Response({}, status=status.HTTP_200_OK)
def destroy(self, request, pk=None): """ 리뷰 삭제 --- <br> <b>헤더</b> - IDREGISTER: (필수) 회원 항번 <br> """ cuid = int(request.META.get('HTTP_IDREGISTER') or 0) user = get_object_or_404(User, id=cuid) try: review_service.reset_rank(cuid) review = get_object_or_404(Review, id=pk, user=user, is_display=True) product = review.product with transaction.atomic(): # 해당 리뷰에 블라인드 사유 삭제 BlindedReview.objects.filter(review_id=pk).delete() # 좋아요 삭제 Reviewlike.objects.filter(writer=user, product=product).delete() # 좋아요 알림 메세지 삭제 MessageBox.objects.filter( user=user, category=MessageCategory.objects.get(name='좋아요'), reference_id=review.id ).update(is_active=False) # review delete review.delete() # user info update user.review_count -= 1 user.score -= 1 user.save() # product info update update_product_info.delay(product.id) # tag update object_tags = TagObject.objects.filter(type='review', object_id=pk) now = local_now().strftime('%Y%m%d%H%M%S') # tag count update for _obj in object_tags: _obj.tag.count -= 1 _obj.tag.modified_date = now _obj.tag.save() # delete tag mapping if object_tags.exists(): object_tags.delete() # elastic delete elasticsearch_reviews.delete(_id=pk) # 레디스와 연동하기 # 처음 리뷰 찾기 first_review = Review_first_log.objects.filter( id=product.id, user=user).all()[:1] is_first = len(first_review) > 0 # 리뷰 포인트 가져오기 review_points = review_service.get_review_points() user_review_count = review_service.get_review_count(user.id) this_week_user_review_count = \ review_service.get_this_week_review_count(user.id) score = review_points['review_point'] + \ ((user_review_count % 3 == 0) * \ review_points['multiple_bonus_point']) + \ (is_first * review_points['first_bonus_point']) # 처음 기존 리뷰 삭제 if is_first is True: first_review[0].delete() # 처음 리뷰 검색후 넣어주기 new_first_reviews = Review.objects.filter( product=product).order_by('_created_at').all()[:2] # 최초 하나는 내 리뷰임으로 두번째 것을 넣어준다. if len(new_first_reviews) > 1: # 넣어준다 Review_first_log( id=product.id, user=new_first_reviews[1].user, timestamp=new_first_reviews[1]._created_at).save() # 레디스는 automic 이 적용되지 않음으로 rdb 에서 동작을 마무리한 후 redis 에 # 적용한다. # 삭제로 리뷰가 0개가 되는 순간 배치에서 감지하지 않음으로 주의해야 한다. # 레디스에 스코어 값 감소시키기 # 리뷰가 정상이면 if review.state == "N" and review.when_seceded == 0 and review.is_display == True and review.user.is_active == 1 and review.user.is_blinded == 0 and review.user.is_black == 0 : # 리뷰가 마지막이었다면 if user_review_count == 1: # rank 에서 삭제 period_zrem('all', user.id) else: # 아니면 감소 period_zincrby('all', user.id, -score) # review 에 _created_at 은 kst 가 기준이기 떄문에 kst 로 비교한다 if iso8601(datetime.strptime( review._created_at, "%Y%m%d%H%M%S")) > \ iso8601(kst_last_week_friday_18_00()): # 이번주 리뷰가 마지막이었다면 if this_week_user_review_count == 1: # 삭제한다 period_zrem('this_week', user.id) else: # 아니면 감소 period_zincrby('this_week', user.id, -score) # 처음 리뷰가 맞고 다른 사람이 쓴 것이 있으면 if is_first is True and len(new_first_reviews) > 1: # 처음 리뷰로 등록된 유저 보너스 점수 레디스에 등록하기 period_zincrby('all', new_first_reviews[1].user.id, review_points['first_bonus_point']) if review._created_at > \ iso8601(kst_last_week_friday_18_00()): period_zincrby('this_week', new_first_reviews[1].user.id, review_points['first_bonus_point']) except: raise return Response({}, status=status.HTTP_200_OK)
def like(self, request, pk=None): """ 리뷰 좋아요 --- 헤더 값 <br> IDREGISTER (필수) """ from django.utils import timezone from libs.utils import utc_now cuid = int(request.META.get('HTTP_IDREGISTER') or 0) try: register = User.objects.get(id=cuid, is_active=True) except: raise InvalidParameterException( _("로그인이 필요합니다.") ) review = get_object_or_404(Review, id=pk) product = review.product writer = review.user response = dict() if register.id == writer.id: raise ConflictException( _("나의 리뷰에는 좋아요 하실 수 없습니다.") ) if Reviewlike.objects.filter(writer=writer, product=product, register=cuid).exists(): raise ConflictException( _("이미 좋아요 하셨습니다.") ) created_at = utc_now() create_date = format_round_datetime(created_at.astimezone(tz=timezone.get_current_timezone())) with transaction.atomic(): # add one Reviewlike( writer=writer, product=product, register=register, create_date=create_date ).save() # writer info update user_updated_info = users_service.get_user_score_info(writer.id) writer.review_count = user_updated_info.get('review_count') writer.like_count = user_updated_info.get('like_count') writer.score = user_updated_info.get('score') writer.save() # review like count update review.like_count = Reviewlike.objects.using('default').filter(writer=writer, product=product).count() review.save() # elastic update body = { "doc": {'likeCount': review.like_count} } elasticsearch_reviews.update(_id=review.id, body=body) # 알림함 try: review_service.make_like_message(review.id, register.id, created_at) except: pass # send push message push_text = "{} 님이 내 리뷰를 좋아합니다.\n{} - {}".format( register.nickname, product.brand.name, product.name ) try: send_push_message( push_text, link_type=17, link_code=product.id, target_id=writer.id, ) except: pass response['is_success'] = True response['message'] = _("좋아요 되었습니다.") return Response(SuccessMessageResponse(response).data, status=status.HTTP_201_CREATED)