import openpyxl from rest_framework import status from rest_framework.views import APIView from rest_framework.response import Response from gauth.models import Location, LocationManager from django.http import Http404 from django.shortcuts import render, redirect from django.views.generic import View from django.contrib import messages from user.forms import StaffRegistrationForm, StaffSheetDateForm, GoogleReviewsFilter, FacebookReviewsFilter from review.models import Review from yelp.models import YelpReview from facebook_app.models import FacebookReview from name_extractor.models import Staff from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger from django.shortcuts import get_object_or_404 from name_extractor.utils import extract_names_from_reviews, make_all_staffs_point_zero from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin from user.utils import ( get_google_review_report, get_facebook_report, get_yelp_review_report, date_str2datetime ) from .forms import ImportStaffSpreadSheet LOC_SYN = { 'cypress-1960': 'cypress', 'collegestation': 'college station' } class LocationListView(View, PermissionRequiredMixin): permission_required = 'is_staff' def post(self, request, *args, **kwargs): form = ImportStaffSpreadSheet(request.POST, request.FILES) if form.is_valid(): staff_file = form.cleaned_data.get('staff_file') wb = openpyxl.load_workbook(staff_file) worksheet = wb.worksheets[0] rows = worksheet.values col_names = next(rows) try: name_idx, loc_idx, dept_idx = col_names.index('Name'), col_names.index('Location'), col_names.index('Job Title') except ValueError: messages.warning(request, "Columns in missing. Check columns ['Name', 'Location', 'Job Title'] again.") return redirect('location-list') # Clear all previously registered staffs staffs = Staff.objects.all() staffs.delete() for row in rows: try: name, loc, dept = row[name_idx], row[loc_idx], row[dept_idx] except IndexError: pass if loc.lower() in ['alllocations', '#n/a']: continue if loc.lower() in LOC_SYN.keys(): loc = LOC_SYN[loc.lower()] location = Location.objects.filter(care_name__icontains=loc).first() if location: Staff.objects.create( name=name, location=location, department=dept ) messages.success(request, 'Staff file upload successfully.') return redirect('location-list') def get(self, request, *args, **kwargs): locations = Location.objects.all() form = ImportStaffSpreadSheet() context = { 'all_locations': locations, 'file_upload_form': form } return render(request, 'locations.html', context=context) class LocationAnalytics(LoginRequiredMixin, View): def get(self, request, location_id, *args, **kwargs): location = Location.objects.get(pk=location_id) google_report = get_google_review_report(location_id) facebook_report = get_facebook_report(location_id) yelp_report = get_yelp_review_report(location_id) context = { 'location': location, 'google_this_month_pos': google_report.get('this_month_pos'), 'google_last_month_pos': google_report.get('last_month_pos'), 'facebook_this_month_pos': facebook_report.get('this_month_pos'), 'facebook_last_month_pos': facebook_report.get('last_month_pos'), 'google_this_month_neg': google_report.get('this_month_neg'), 'google_last_month_neg': google_report.get('last_month_neg'), 'facebook_this_month_neg': facebook_report.get('this_month_neg'), 'facebook_last_month_neg': facebook_report.get('last_month_neg'), 'yelp': yelp_report } return render(request, 'manager-dashboard.html', context=context) class ReviewListLocationWise(View): def get(self, request, platform, location_id, *args, **kwargs): location = Location.objects.get(pk=location_id) if platform == 'google': form = GoogleReviewsFilter() reviews = Review.objects.filter(location_id=location_id).order_by('-update_time') elif platform == 'facebook': form = FacebookReviewsFilter() reviews = FacebookReview.objects.filter(page__location_id=location_id).order_by('-create_time') elif platform == 'yelp': form = GoogleReviewsFilter() reviews = YelpReview.objects.filter(location__location_id=location_id).order_by('-date_posted') else: raise Http404() page = request.GET.get('page', 1) paginator = Paginator(reviews, 50) try: reviews = paginator.page(page) except PageNotAnInteger: reviews = paginator.page(1) except EmptyPage: reviews = paginator.page(paginator.num_pages) context = {'reviews': reviews, 'platform': platform, 'location': location, 'form': form} return render(request, 'review-list-man.html', context=context) def post(self, request, platform, location_id, *args, **kwargs): location = Location.objects.get(pk=location_id) if platform == 'google': form = GoogleReviewsFilter(data=request.POST) start_date = date_str2datetime(request.POST.get('start_date')) end_date = date_str2datetime(request.POST.get('end_date')) if end_date < start_date: start_date, end_date = end_date, start_date star_rating = int(request.POST.get('star_ratings')) reviews = Review.objects.filter(location_id=location_id).order_by('-update_time') if start_date and end_date: if star_rating > 5: reviews = reviews.filter(create_time__range=(start_date, end_date)) else: reviews = reviews.filter(create_time__range=(start_date, end_date), star_rating=star_rating) elif platform == 'yelp': form = GoogleReviewsFilter(data=request.POST) start_date = date_str2datetime(request.POST.get('start_date')) end_date = date_str2datetime(request.POST.get('end_date')) if end_date < start_date: start_date, end_date = end_date, start_date star_rating = int(request.POST.get('star_ratings')) reviews = YelpReview.objects.filter(location__location_id=location_id).order_by('-date_posted') if start_date and end_date: if star_rating > 5: reviews = reviews.filter(date_posted__range=(start_date, end_date)) else: reviews = reviews.filter(date_posted__range=(start_date, end_date), rating=star_rating) elif platform == 'facebook': form = FacebookReviewsFilter(request.POST) start_date = date_str2datetime(request.POST.get('start_date')) end_date = date_str2datetime(request.POST.get('end_date')) star_rating = int(request.POST.get('star_ratings')) reviews = FacebookReview.objects.filter(page__location_id=location_id).order_by('-create_time') if start_date and end_date: if star_rating > 5: reviews = reviews.filter(create_time__range=(start_date, end_date)) else: reviews = reviews.filter(create_time__range=(start_date, end_date), recommendation_type=bool(star_rating)) else: raise Http404() page = request.GET.get('page', 1) paginator = Paginator(reviews, 50) try: reviews = paginator.page(page) except PageNotAnInteger: reviews = paginator.page(1) except EmptyPage: reviews = paginator.page(paginator.num_pages) context = {'reviews': reviews, 'platform': platform, 'location': location, 'form': form} return render(request, 'review-list-man.html', context=context) class ReviewAnalyticsGraph(View): def get(self, request, location_id, *args, **kwargs): location = Location.objects.get(pk=location_id) return render(request, 'location-wise-reviews-man.html', context={'location': location}) class StaffLeaderBoard(View): def get(self, request, location_id, *args, **kwargs): location = Location.objects.get(pk=location_id) staffs = Staff.objects.filter(location=location).order_by('-total_units') form = StaffRegistrationForm() date_form = StaffSheetDateForm() context = { 'location': location, 'staffs': staffs, 'date_form': date_form, 'form': form } return render(request, 'staff_list_man.html', context) def post(self, request, location_id, *args, **kwargs): form = StaffRegistrationForm(request.POST) if form.is_valid(): name = form.cleaned_data.get('name') department = form.cleaned_data.get('department') nick_names = form.cleaned_data.get('nick_names') staff = Staff.objects.create( name=name, location_id=location_id, department=department, nick_names=nick_names ) messages.success(request, f'A new staff {staff} has been created!') return redirect('staff-leaderboard-man', location_id=location_id) class SyncStaffLeaderBoard(View): def post(self, request, location_id, *args, **kwargs): start_date = date_str2datetime(request.POST.get('start_date')) end_date = date_str2datetime(request.POST.get('end_date')) extract_names_from_reviews( start_date=start_date, end_date=end_date, location_id=location_id ) return redirect('staff-leaderboard-man', location_id=location_id) class StaffDelete(View): def get(self, request, staff_id, *args, **kwargs): staff = get_object_or_404(Staff, id=staff_id) staff.delete() return redirect('staff-leaderboard-man', location_id=staff.location_id) class AllLocationSummary(APIView): def get(self, request, *args, **kwargs): days = request.GET['days'] if not days: return Response({'error': 'No location Found'}, status=status.HTTP_400_BAD_REQUEST) locations = Location.objects.all() review_counts = [] max_rev = 0 for location in locations: loc_json = { 'name': location.care_name, 'positive': [ location.last_week_pos_google_review_count, location.last_week_pos_facebook_review_count, location.last_week_pos_yelp_review_count ], 'negative': [ location.last_week_neg_google_review_count, location.last_week_neg_facebook_review_count, location.last_week_neg_yelp_review_count ] } _temp_max = max(loc_json['positive']+loc_json['negative']) if _temp_max > max_rev: max_rev = _temp_max review_counts.append(loc_json) response = { 'labels': ['Google', 'Facebook', 'Yelp'], 'review_counts': review_counts, 'max_rev_count': max_rev, } return Response(response)