import warnings from io import BytesIO import pandas as pd from django.db.models import Q from django.http import HttpResponse, JsonResponse from django.http import HttpResponse from django.http import JsonResponse from rest_framework import status from rest_framework import status as http_status from rest_framework.decorators import action from rest_framework.decorators import api_view from rest_framework.decorators import action, api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from rest_framework.views import APIView from rest_framework.viewsets import ReadOnlyModelViewSet from service import models from service import pagination from service import serializers from service import utils from service.permissions import UserPermission from service.utils import load_data class AOViewSet(ReadOnlyModelViewSet): serializer_class = serializers.AOSerializer queryset = models.AO.objects permission_classes = [UserPermission] class PlacementPointViewSet(ReadOnlyModelViewSet): serializer_class = serializers.PlacementPointSerializer queryset = models.PlacementPoint.objects pagination_class = pagination.MyPagination permission_classes = [UserPermission] def get_queryset(self): qs = self.queryset.all() location_ids = self.request.GET.get('location_ids[]') prediction_first = self.request.GET.get('prediction_first[]') prediction_current = self.request.GET.get('prediction_current[]') categories = self.request.GET.get('categories[]') status = self.request.GET.get('status[]') delta = self.request.GET.get('delta[]') fact = self.request.GET.get('fact[]') age = self.request.GET.get('age[]') included = self.request.GET.get('included[]') excluded = self.request.GET.get('excluded[]') plan_first = self.request.GET.get('plan_first[]') plan_current = self.request.GET.get('plan_current[]') rayons = self.request.GET.get('rayon[]') aos = self.request.GET.get('ao[]') if location_ids: location_ids = list(location_ids.split(',')) qs = qs.filter(pk__in=location_ids) if prediction_first: prediction_first = list(prediction_first.split(',')) qs = qs.filter(prediction_first__range=prediction_first) if prediction_current: prediction_current = list(prediction_current.split(',')) qs = qs.filter(prediction_current__range=prediction_current) if categories: categories = list(categories.split(',')) qs = qs.filter(category__in=categories) if status: status = list(status.split(',')) qs = qs.filter(status__in=status) if delta: delta = list(delta.split(',')) qs = qs.filter(delta__range=delta) if fact: fact = list(fact.split(',')) qs = qs.filter(fact__range=fact) if age: age = list(age.split(',')) qs = qs.filter(age__range=age) if plan_first: plan_first = list(plan_first.split(',')) qs = qs.filter(plan_first__range=plan_first) if plan_current: plan_current = list(plan_current.split(',')) qs = qs.filter(plan_current__range=plan_current) if rayons: rayons = list(rayons.split(',')) qs = qs.filter(rayon_id__in=rayons) if aos: aos = list(aos.split(',')) qs = qs.filter(okrug_id__in=aos) if excluded: excluded = list(excluded.split(',')) qs = qs.filter(~Q(pk__in=excluded)) if included: inclded = list(included.split(',')) qs2 = models.PlacementPoint.objects.filter(pk__in=inclded).all() qs = (qs | qs2).distinct() return qs @action(detail=False, methods=['get']) def filters(self, request): qs = self.get_queryset() age_day = [x for x in list(set(qs.values_list('age_day', flat=True))) if x is not None] prediction_first = [x for x in list( set(qs.values_list('prediction_first', flat=True))) if x is not None] prediction_current = [x for x in list( set(qs.values_list('prediction_current', flat=True))) if x is not None] plan_first = [x for x in list(set(qs.values_list('plan_first', flat=True))) if x is not None] plan_current = [x for x in list(set(qs.values_list('plan_current', flat=True))) if x is not None] fact = [x for x in list(set(qs.values_list('fact', flat=True))) if x is not None] delta_first = [x for x in list(set(qs.values_list('delta_first', flat=True))) if x is not None] delta_current = [x for x in list(set(qs.values_list('delta_current', flat=True))) if x is not None] flat_cnt = [x for x in list(set(qs.values_list('flat_cnt', flat=True))) if x is not None] year_bld = [x for x in list(set(qs.values_list('year_bld', flat=True))) if x is not None] levels = [x for x in list(set(qs.values_list('levels', flat=True))) if x is not None] doors = [x for x in list(set(qs.values_list('doors', flat=True))) if x is not None] flats_cnt = [x for x in list(set(qs.values_list('flats_cnt', flat=True))) if x is not None] popul_home = [x for x in list(set(qs.values_list('popul_home', flat=True))) if x is not None] popul_job = [x for x in list(set(qs.values_list('popul_job', flat=True))) if x is not None] other_post_cnt = [x for x in list( set(qs.values_list('other_post_cnt', flat=True))) if x is not None] target_post_cnt = [x for x in list( set(qs.values_list('target_post_cnt', flat=True))) if x is not None] yndxfood_cnt = [x for x in list(set(qs.values_list('yndxfood_cnt', flat=True))) if x is not None] yndxfood_sum = [x for x in list(set(qs.values_list('yndxfood_sum', flat=True))) if x is not None] yndxfood_cnt_cst = [x for x in list( set(qs.values_list('yndxfood_cnt_cst', flat=True))) if x is not None] data = { "age_day": [min(age_day), max(age_day)] if age_day else [0, 2030], "prediction_first": [min(prediction_first), max( prediction_first)] if prediction_first else [-22, 22], "prediction_current": [min(prediction_current), max( prediction_current)] if prediction_current else [-22, 22], "plan_first": [min(plan_first), max(plan_first)] if plan_first else [0, 100], "plan_current": [min(plan_current), max(plan_current)] if plan_current else [0, 100], "fact": [min(fact), max(fact)] if fact else [0, 100], "delta_first": [min(delta_first), max(delta_first)] if delta_first else [0, 100], "delta_current": [min(delta_current), max(delta_current)] if delta_current else [0, 100], "flat_cnt": [min(flat_cnt), max(flat_cnt)] if flat_cnt else [0, 100], "year_bld": [min(year_bld), max(year_bld)] if year_bld else [0, 2030], "levels": [min(levels), max(levels)] if levels else [0, 100], "doors ": [min(doors), max(doors)] if doors else [0, 100], "flats_cnt": [min(flats_cnt), max(flats_cnt)] if flats_cnt else [0, 100], "popul_home": [min(popul_home), max(popul_home)] if popul_home else [0, 100], "popul_job": [min(popul_job), max(popul_job)] if popul_job else [0, 100], "other_post_cnt": [min(other_post_cnt), max(other_post_cnt)] if other_post_cnt else [0, 100], "target_post_cnt": [min(target_post_cnt), max(target_post_cnt)] if target_post_cnt else [ 0, 100], "yndxfood_cnt": [min(yndxfood_cnt), max(yndxfood_cnt)] if yndxfood_cnt else [0, 100], "yndxfood_sum": [min(yndxfood_sum), max(yndxfood_sum)] if yndxfood_sum else [0, 100], "yndxfood_cnt_cst": [min(yndxfood_cnt_cst), max( yndxfood_cnt_cst)] if yndxfood_cnt_cst else [0, 100], } return Response(data, status=status.HTTP_200_OK) @action(detail=False, methods=['get']) def search_address(self, request): address = self.request.GET.get('address') qs = self.get_queryset() qs = qs.filter(address__icontains=address) page = self.paginate_queryset(qs) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) serializer = self.get_serializer(qs, many=True) return Response(serializer.data) @action(detail=False, methods=['put']) def update_status(self, request): qs = self.get_queryset() new_status = self.request.GET.get('status') if not new_status: return Response({'message': 'No status'}, 400) qs.update(**{'status': new_status}) return Response({'message': 'status updated'}, status=http_status.HTTP_200_OK) @action(detail=False, methods=['put']) def update_fact(self, request): point_id = request.GET.get('location_id') fact = request.GET.get('fact') if not point_id or not fact or not fact.isdigit(): return Response(status=http_status.HTTP_400_BAD_REQUEST) qs = models.PlacementPoint.objects.filter(pk_id=point_id) if not qs: return Response(status=http_status.HTTP_404_NOT_FOUND) qs.update(**{'fact': fact}) return Response({'message': 'fact updated'}, status=http_status.HTTP_200_OK) @action(detail=False, methods=['get']) def to_excel(self, request): qs = self.get_queryset() data = pd.DataFrame(list(qs.values())) data['start_date'] = data['start_date'].dt.tz_localize(None) data['sample_trn'] = data['sample_trn'].astype(int) with BytesIO() as b: with pd.ExcelWriter(b) as writer: data.to_excel(writer, sheet_name="Placement Points", index=False) filename = 'placement_points.xlsx' res = HttpResponse( b.getvalue(), content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', ) res['Content-Disposition'] = f'attachment; filename={filename}' return res @action(detail=False, methods=['get']) def get_10k(self, request): if models.PlacementPoint.objects.count() > 10000: qs = \ models.PlacementPoint.objects.order_by( '-prediction_current').all()[ 10000] return Response({'prediction_current': qs.prediction_current}, 200) return Response( {'prediction_current': models.PlacementPoint.objects.order_by( 'prediction_current').first().prediction_current}, 200) class refresh_placement_points(APIView): @staticmethod def post(request): warnings.filterwarnings('ignore') file = request.FILES['file'] load_data(file) return Response(status=http_status.HTTP_200_OK) class load_ao_and_rayons(APIView): @staticmethod def post(request): warnings.filterwarnings('ignore') file_ao = request.FILES['file_ao'] file_rayon = request.FILES['file_rayon'] utils.load_ao_and_rayons(file_ao, file_rayon) return Response(status=http_status.HTTP_200_OK) @api_view(['POST']) def upload_rivals(request): warnings.filterwarnings('ignore') file_rivals = request.FILES['file_rivals'] utils.load_rivals(file_rivals) return JsonResponse({'message': 'OK'}) @api_view(['POST']) def upload_dist(request): warnings.filterwarnings('ignore') file_dist = request.FILES['file_dist'] utils.load_dist(file_dist) return JsonResponse({'message': 'OK'}) @api_view(['GET']) @permission_classes([IsAuthenticated]) def get_current_user(request): return JsonResponse( {'groups': [gr.name for gr in request.user.groups.all()]})