You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

313 lines
13 KiB

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()]})