utils.py 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. import numpy as np
  2. from django.utils import timezone
  3. from django.db import connection
  4. from django.db.models import Count
  5. from review.models import Review
  6. from facebook_app.models import FacebookReview, FacebookPage
  7. from yelp.models import YelpReview, YelpLocation
  8. DATE_IDENTIFIER = {
  9. 'google': 'create_time',
  10. 'yelp': 'date_posted',
  11. 'facebook': 'create_time'
  12. }
  13. REVIEW_IDENTIFIER = {
  14. 'google': 'star_rating',
  15. 'yelp': 'rating',
  16. 'facebook': 'recommendation_type'
  17. }
  18. TABLE_NAME = {
  19. 'google': 'review_review',
  20. 'facebook': 'facebook_app_facebookreview',
  21. 'yelp': 'yelp_yelpreview'
  22. }
  23. now = timezone.now()
  24. beginning_of_month = now.replace(day=1, hour=0, minute=0, second=0)
  25. beginning_of_last_month = now - timezone.timedelta(days=now.day+31)
  26. def get_google_review_report(location_id):
  27. pos = Review.objects.filter(
  28. location_id=location_id,
  29. create_time__range=(beginning_of_month, now),
  30. star_rating__gte=3
  31. ).count()
  32. neg = Review.objects.filter(
  33. location_id=location_id,
  34. create_time__range=(beginning_of_month, now),
  35. star_rating__lte=2
  36. ).count()
  37. pos_last_month = Review.objects.filter(
  38. location_id=location_id,
  39. create_time__range=(beginning_of_last_month, beginning_of_month),
  40. star_rating__gte=3
  41. ).count()
  42. neg_last_month = Review.objects.filter(
  43. location_id=location_id,
  44. create_time__range=(beginning_of_last_month, beginning_of_month),
  45. star_rating__lte=2
  46. ).count()
  47. pos_growth = 'inf' if pos_last_month == 0 else round(((((pos / now.day) * 30) - pos_last_month) / pos_last_month) * 100, 2)
  48. neg_growth = 'inf' if neg_last_month == 0 else round(((((neg / now.day) * 30) - neg_last_month) / neg_last_month) * 100, 2)
  49. total = pos + neg
  50. last_month_total = pos_last_month + neg_last_month
  51. total_growth = 'inf' if last_month_total == 0 else round(((((total / now.day) * 30) - last_month_total) / last_month_total) * 100, 2)
  52. return {
  53. 'positive': pos,
  54. 'positive_growth': pos_growth,
  55. 'negative': neg,
  56. 'negative_growth': neg_growth,
  57. 'total': total,
  58. 'total_growth': total_growth
  59. }
  60. def get_facebook_report(location_id):
  61. pos = FacebookReview.objects.filter(
  62. page__location_id=location_id,
  63. create_time__range=(beginning_of_month, now),
  64. recommendation_type=True
  65. ).count()
  66. neg = FacebookReview.objects.filter(
  67. page__location_id=location_id,
  68. create_time__range=(beginning_of_month, now),
  69. recommendation_type=False
  70. ).count()
  71. pos_last_month = FacebookReview.objects.filter(
  72. page__location_id=location_id,
  73. create_time__range=(beginning_of_last_month, beginning_of_month),
  74. recommendation_type=True
  75. ).count()
  76. neg_last_month = FacebookReview.objects.filter(
  77. page__location_id=location_id,
  78. create_time__range=(beginning_of_last_month, beginning_of_month),
  79. recommendation_type=False
  80. ).count()
  81. pos_growth = 'inf' if pos_last_month == 0 else round(((((pos / now.day) * 30) - pos_last_month) / pos_last_month) * 100, 2)
  82. neg_growth = 'inf' if neg_last_month == 0 else round(((((neg / now.day) * 30) - neg_last_month) / neg_last_month) * 100, 2)
  83. total = pos + neg
  84. last_month_total = pos_last_month + neg_last_month
  85. total_growth = 'inf' if last_month_total == 0 else round(((((total / now.day) * 30) - last_month_total) / last_month_total) * 100, 2)
  86. return {
  87. 'positive': pos,
  88. 'positive_growth': pos_growth,
  89. 'negative': neg,
  90. 'negative_growth': neg_growth,
  91. 'total': total,
  92. 'total_growth': total_growth
  93. }
  94. def get_yelp_review_report(location_id):
  95. pos = YelpReview.objects.filter(
  96. location__location_id=location_id,
  97. date_posted__range=(beginning_of_month, now),
  98. rating__gte=3
  99. ).count()
  100. neg = YelpReview.objects.filter(
  101. location__location_id=location_id,
  102. date_posted__range=(beginning_of_month, now),
  103. rating__lte=2
  104. ).count()
  105. pos_last_month = YelpReview.objects.filter(
  106. location__location_id=location_id,
  107. date_posted__range=(beginning_of_last_month, beginning_of_month),
  108. rating__gte=3
  109. ).count()
  110. neg_last_month = YelpReview.objects.filter(
  111. location__location_id=location_id,
  112. date_posted__range=(beginning_of_last_month, beginning_of_month),
  113. rating__lte=2
  114. ).count()
  115. pos_growth = 'inf' if pos_last_month == 0 else round(((((pos / now.day) * 30) - pos_last_month) / pos_last_month) * 100, 2)
  116. neg_growth = 'inf' if neg_last_month == 0 else round(((((neg / now.day) * 30) - neg_last_month) / neg_last_month) * 100, 2)
  117. total = pos + neg
  118. last_month_total = pos_last_month + neg_last_month
  119. total_growth = 'inf' if last_month_total == 0 else round(((((total / now.day) * 30) - last_month_total) / last_month_total) * 100, 2)
  120. return {
  121. 'positive': pos,
  122. 'positive_growth': pos_growth,
  123. 'negative': neg,
  124. 'negative_growth': neg_growth,
  125. 'total': total,
  126. 'total_growth': total_growth
  127. }
  128. def get_this_month_analytics(location_id):
  129. google_qs = Review.objects.filter(
  130. create_time__range=(beginning_of_month, now),
  131. location_id=location_id
  132. )\
  133. .values('create_time__day')\
  134. .annotate(total=Count('create_time__day'))
  135. google_qs_dict = {q['create_time__day']: q['total'] for q in google_qs}
  136. yelp_qs = YelpReview.objects.filter(
  137. location__location_id=location_id,
  138. date_posted__range=(beginning_of_month, now),
  139. )\
  140. .values('date_posted__day')\
  141. .annotate(total=Count('date_posted__day'))
  142. yelp_qs_dict = {q['date_posted__day']: q['total'] for q in yelp_qs}
  143. facebook_qs = FacebookReview.objects.filter(
  144. page__location_id=location_id,
  145. create_time__range=(beginning_of_month, now),
  146. )\
  147. .values('create_time__day')\
  148. .annotate(total=Count('create_time__day'))
  149. facebook_qs_dict = {q['create_time__day']: q['total'] for q in facebook_qs}
  150. label = []
  151. facebook = []
  152. yelp = []
  153. google = []
  154. for day in range(1, now.day+1):
  155. label.append(day)
  156. facebook.append(facebook_qs_dict.get(day, 0))
  157. yelp.append(yelp_qs_dict.get(day, 0))
  158. google.append(google_qs_dict.get(day, 0))
  159. return {
  160. 'label': label,
  161. 'google': google,
  162. 'facebook': facebook,
  163. 'yelp': yelp
  164. }
  165. def get_review_count_by_month(location_id, platform):
  166. now = timezone.now()
  167. date = now.replace(day=1) - timezone.timedelta(days=1)
  168. day = date.day - now.day
  169. curr_month = {
  170. }
  171. if platform == 'google':
  172. loc_id = location_id
  173. field_name = 'location_id'
  174. curr_month_data = Review.objects.filter(create_time__gte=date, location_id=location_id).values('star_rating')\
  175. .annotate(total=Count('star_rating')).order_by('star_rating')
  176. curr_month['label'] = [r.get('star_rating') for r in curr_month_data]
  177. curr_month['total'] = [r.get('total') for r in curr_month_data]
  178. elif platform == 'yelp':
  179. loc_id = YelpLocation.objects.get(location_id=location_id).id
  180. field_name = 'location_id'
  181. curr_month_data = YelpReview.objects.filter(date_posted__gte=date, location__location_id=location_id)\
  182. .values('rating').annotate(total=Count('rating')).order_by('rating')
  183. curr_month['label'] = [r.get('rating') for r in curr_month_data]
  184. curr_month['total'] = [r.get('total') for r in curr_month_data]
  185. elif platform == 'facebook':
  186. loc_id = FacebookPage.objects.get(location_id=location_id).id
  187. field_name = 'page_id'
  188. curr_month_data = FacebookReview.objects.filter(create_time__gte=date, page__location_id=location_id)\
  189. .values('recommendation_type').annotate(total=Count('recommendation_type'))
  190. curr_month['label'] = ['Recommended' if r.get('recommendation_type') else 'Not Recommended' for r in curr_month_data]
  191. curr_month['total'] = [r.get('total') for r in curr_month_data]
  192. else:
  193. raise ValueError(f'No platform name {platform}')
  194. sql = f'''
  195. SELECT MONTHNAME({DATE_IDENTIFIER[platform]}) as month, {REVIEW_IDENTIFIER[platform]}, COUNT(*) as total_review
  196. FROM {TABLE_NAME[platform]}
  197. WHERE DATE_ADD(DATE_ADD(CURRENT_TIMESTAMP(),
  198. INTERVAL -1 YEAR), INTERVAL {day} DAY) <= {DATE_IDENTIFIER[platform]} and {field_name}={loc_id}
  199. GROUP BY MONTHNAME({DATE_IDENTIFIER[platform]}), {REVIEW_IDENTIFIER[platform]}
  200. ORDER BY {DATE_IDENTIFIER[platform]};
  201. '''
  202. with connection.cursor() as cursor:
  203. cursor.execute(sql)
  204. rows = cursor.fetchall()
  205. # It will transform a cursor like (('September', 5, 26), ('October', 3, 21), ...)
  206. # to a dict like this {('September', 5): 26, ('October', 3): 21), ...}
  207. # Here key tuple ('September', 5) means 5 star ratings in September month and value is the number of star count.
  208. row_dict = {(row[0], row[1]): row[2] for row in rows}
  209. # Get all month names for graph label
  210. labels = []
  211. for row in rows:
  212. if row[0] not in labels:
  213. labels.append(row[0])
  214. star_ratings = []
  215. if platform == 'facebook':
  216. for i in range(2):
  217. row = [row_dict.get((m, i), 0) for m in labels]
  218. star_ratings.append(row)
  219. else:
  220. for i in range(1, 6):
  221. row = [row_dict.get((m, i), 0) for m in labels]
  222. star_ratings.append(row)
  223. total_review = list(np.sum(star_ratings, axis=0))
  224. response = {
  225. 'total_review': total_review,
  226. 'labels': labels,
  227. 'star_rating': star_ratings,
  228. 'curr_month': curr_month
  229. }
  230. return response