utils.py 10.0 KB

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