diff --git a/PrePlacementPoints.xlsx b/PrePlacementPoints.xlsx index 80027fe..a508bb3 100644 Binary files a/PrePlacementPoints.xlsx and b/PrePlacementPoints.xlsx differ diff --git a/service/admin.py b/service/admin.py index f579e59..0977e67 100644 --- a/service/admin.py +++ b/service/admin.py @@ -12,7 +12,7 @@ from service.models import PlacementPoint from service.models import Rayon from service.models import PrePlacementPoint, Post_and_pvz, Post_and_pvzCategory, Post_and_pvzGroup, OtherObjects, \ OtherObjectsGroup, \ - OtherObjectsCategory, PrePlacementPointPVZDistance, TempFiles, RaschetGroups + OtherObjectsCategory, PrePlacementPointPVZDistance, TempFiles, RaschetGroups, House from service.models import PlacementPointPVZDistance, TaskStatus from postamates.settings import DEBUG from django.core.cache import cache @@ -44,6 +44,7 @@ class Post_and_PVZAdmin(admin.ModelAdmin): my_admin_site.register(Post_and_pvz, Post_and_PVZAdmin) my_admin_site.register(OtherObjects) +my_admin_site.register(House) my_admin_site.register(PrePlacementPoint) my_admin_site.register(PrePlacementPointPVZDistance) diff --git a/service/migrations/0036_house.py b/service/migrations/0036_house.py new file mode 100644 index 0000000..8b1845a --- /dev/null +++ b/service/migrations/0036_house.py @@ -0,0 +1,32 @@ +# Generated by Django 3.2 on 2023-10-02 09:21 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('service', '0035_auto_20230928_1519'), + ] + + operations = [ + migrations.CreateModel( + name='House', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('year_bld', models.IntegerField(blank=True, null=True)), + ('mat_nes', models.TextField(blank=True, null=True)), + ('flat_cnt', models.IntegerField(blank=True, null=True)), + ('levels', models.TextField(blank=True, null=True)), + ('doors', models.IntegerField(blank=True, null=True)), + ('enrg_cls', models.TextField(blank=True, null=True)), + ('street', models.TextField(blank=True, null=True)), + ('house_number', models.TextField(blank=True, null=True)), + ], + options={ + 'verbose_name': 'Дом', + 'verbose_name_plural': 'Дома', + 'ordering': ('id',), + }, + ), + ] diff --git a/service/migrations/0037_auto_20231002_1349.py b/service/migrations/0037_auto_20231002_1349.py new file mode 100644 index 0000000..f18ef38 --- /dev/null +++ b/service/migrations/0037_auto_20231002_1349.py @@ -0,0 +1,23 @@ +# Generated by Django 3.2 on 2023-10-02 10:49 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('service', '0036_house'), + ] + + operations = [ + migrations.AlterField( + model_name='placementpoint', + name='levels', + field=models.TextField(blank=True, null=True), + ), + migrations.AlterField( + model_name='preplacementpoint', + name='levels', + field=models.TextField(blank=True, null=True), + ), + ] diff --git a/service/models.py b/service/models.py index 0522d09..9dd5246 100644 --- a/service/models.py +++ b/service/models.py @@ -30,7 +30,7 @@ class AbstractPlacementPoint(models.Model): sample_trn = models.BooleanField(null=True, blank=True) flat_cnt = models.IntegerField(null=True, blank=True, verbose_name='Количество квартир') year_bld = models.IntegerField(null=True, blank=True, verbose_name='Год постройки') - levels = models.IntegerField(null=True, blank=True) + levels = models.TextField(null=True, blank=True) enrg_cls = models.TextField(null=True, blank=True) mat_nes = models.TextField(null=True, blank=True) doors = models.IntegerField(null=True, blank=True) @@ -278,3 +278,20 @@ class RaschetGroups(models.Model): class RaschetObjects(models.Model): obj_id = models.IntegerField(null=False, blank=False) + + +class House(models.Model): + class Meta: + verbose_name = 'Дом' + verbose_name_plural = 'Дома' + ordering = ('id',) + + year_bld = models.IntegerField(blank=True,null=True) + mat_nes = models.TextField(blank=True,null=True) + flat_cnt = models.IntegerField(blank=True, null=True) + levels = models.TextField(blank=True,null=True) + doors = models.IntegerField(blank=True, null=True) + enrg_cls = models.TextField(blank=True,null=True) + street = models.TextField(blank=True,null=True) + house_number = models.TextField(blank=True,null=True) + diff --git a/service/service.py b/service/service.py index 757db97..83a9cd0 100644 --- a/service/service.py +++ b/service/service.py @@ -40,29 +40,36 @@ class PointService: req_url = f"https://geocode.search.hereapi.com/v1/geocode?q={addr}&apiKey={GEOCODER_API_KEY}" response = requests.get(req_url).json().get('items') if not response: - models.PrePlacementPoint.objects.create(address=addr, matching_status=MatchingStatus.Error.name, status=PointStatus.Pending.name) + models.PrePlacementPoint.objects.create(address=addr, matching_status=MatchingStatus.Error.name, + status=PointStatus.Pending.name) problem += 1 continue coords = response[0].get('position') if not coords: - models.PrePlacementPoint.objects.create(address=addr, matching_status=MatchingStatus.Error.name, status=PointStatus.Pending.name) + models.PrePlacementPoint.objects.create(address=addr, matching_status=MatchingStatus.Error.name, + status=PointStatus.Pending.name) problem += 1 continue wkt = "POINT(" + str(coords['lng']) + " " + str(coords['lat']) + ")" response = response[0]['address'] obj = models.PlacementPoint.objects.filter(street=response.get('street'), house_number=response.get('houseNumber'), - category=cat).values().first() + category=cat).values() rayon = models.Rayon.objects.filter(polygon__intersects=wkt).first() if obj: - distances = models.PlacementPointPVZDistance.objects.filter(placement_point=obj.get('id')).all() - obj.pop('id') - pre_obj, _ = models.PrePlacementPoint.objects.get_or_create( - **{**obj, "matching_status": MatchingStatus.Matched.name}) - for d in distances: - models.PrePlacementPointPVZDistance.objects.get_or_create(placement_point=pre_obj, - pvz_postamates_group=d.pvz_postamates_group, - dist=d.dist) + if cat == 'Подъезд жилого дома': + objs = obj.all() + else: + objs = [obj.first()] + for o in objs: + distances = models.PlacementPointPVZDistance.objects.filter(placement_point=o.get('id')).all() + o.pop('id') + pre_obj, _ = models.PrePlacementPoint.objects.get_or_create( + **{**o, "matching_status": MatchingStatus.Matched.name}) + for d in distances: + models.PrePlacementPointPVZDistance.objects.get_or_create(placement_point=pre_obj, + pvz_postamates_group=d.pvz_postamates_group, + dist=d.dist) matched += 1 elif not rayon: @@ -75,6 +82,28 @@ class PointService: matching_status=MatchingStatus.Error.name, status=PointStatus.Pending.name) problem += 1 + elif cat == 'Подъезд жилого дома': + houses = models.House.objects.filter(street=response.get('street'), + house_number=response.get('houseNumber')).values().all() + for house in houses: + house.pop('id') + if house.get('doors') and house.get('doors') != 0: + house['flat_cnt'] = int(house['flat_cnt'] / house['doors']) + for _num in range(house['doors']): + models.PrePlacementPoint.objects.get_or_create(**house, address=addr, + name=f'Подъезд {_num + 1}', + matching_status=MatchingStatus.New.name, + sample_trn=False, + is_vis=True, geometry=wkt, + status=PointStatus.Pending.name, area=rayon, + district=rayon.AO) + else: + models.PrePlacementPoint.objects.get_or_create(**house, address=addr, + matching_status=MatchingStatus.New.name, + sample_trn=False, + is_vis=True, geometry=wkt, + status=PointStatus.Pending.name, area=rayon, + district=rayon.AO) else: models.PrePlacementPoint.objects.get_or_create(address=addr, street=response.get('street'), house_number=response.get('houseNumber'), diff --git a/service/urls.py b/service/urls.py index 69d3e6d..cd63db6 100644 --- a/service/urls.py +++ b/service/urls.py @@ -15,6 +15,7 @@ urlpatterns += [ url(r'load_csv/', views.refresh_placement_points.as_view(), name='upload_placement_points'), url(r'upload_post_and_pvz/', views.upload_post_and_pvz, name='upload_post_and_pvz'), url(r'upload_other_objects/', views.upload_other_objects, name='upload_other_objects'), + url(r'upload_houses/', views.upload_houses, name='upload_houses'), url(r'me/', views.get_current_user, name='me'), url('download_pvz_template/', views.download_pvz_template, name='download_pvz_template'), url('download_other_template/', views.download_other_template, name='download_other_template'), diff --git a/service/utils.py b/service/utils.py index 197ac46..d835549 100644 --- a/service/utils.py +++ b/service/utils.py @@ -17,6 +17,7 @@ from rest_framework.viewsets import ReadOnlyModelViewSet import psycopg2 from postamates.settings import DB_URL + def run_sql_command(command): connection = psycopg2.connect( DB_URL @@ -81,7 +82,7 @@ def load_dist(filepath: str): def log_to_telegram(msg): requests.post('https://api.telegram.org/bot6275517704:AAHVp_qv9d9NU740JJdOM2fJdgS4r1AgJrw/sendMessage', - json={"chat_id": "-555238820", "text": str(settings.DOMAIN)+'\n'+msg}) + json={"chat_id": "-555238820", "text": str(settings.DOMAIN) + '\n' + msg}) def cached_func(key, func, timeout=settings.CACHE_TIMEOUT, *args, **kwargs): @@ -103,3 +104,12 @@ class CustomReadOnlyModelViewSet(ReadOnlyModelViewSet): def create_columns_dist(row): return pd.Series(row['min_distance_to_group']) + + +def load_houses(filepath: str): + models.House.objects.all().delete() + df = pd.read_csv(filepath) + df = df.replace(np.nan, None) + df = df.replace('NaT', None) + for row in df.to_dict('records'): + models.House.objects.create(**row) diff --git a/service/views.py b/service/views.py index 054cbd1..405bd76 100644 --- a/service/views.py +++ b/service/views.py @@ -187,10 +187,10 @@ class PlacementPointViewSet(ReadOnlyModelViewSet): if group_dists_lt: g_d = [list(g.split(',')) for g in group_dists_lt] for group in g_d: - if basename=='preplacementpoint': + if basename == 'preplacementpoint': filtered_points = list( models.PrePlacementPointPVZDistance.objects.filter(pvz_postamates_group__id=int(group[0]), - dist__lt=int(group[1])).values_list( + dist__lt=int(group[1])).values_list( 'placement_point__id', flat=True)) else: filtered_points = list( @@ -201,10 +201,10 @@ class PlacementPointViewSet(ReadOnlyModelViewSet): if group_dists_gt: g_d = [list(g.split(',')) for g in group_dists_gt] for group in g_d: - if basename=='preplacementpoint': + if basename == 'preplacementpoint': filtered_points = list( models.PrePlacementPointPVZDistance.objects.filter(pvz_postamates_group__id=int(group[0]), - dist__gt=int(group[1])).values_list( + dist__gt=int(group[1])).values_list( 'placement_point__id', flat=True)) else: filtered_points = list( @@ -396,7 +396,7 @@ class PrePlacementPointViewSet(PlacementPointViewSet): obj.pop('id') ao = obj.pop('district') rayon = obj.pop('area') - obj['district']=models.AO.objects.get(id=ao) + obj['district'] = models.AO.objects.get(id=ao) obj['area'] = models.Rayon.objects.get(id=rayon) obj['age_day'] = 1 new_obj = models.PlacementPoint.objects.create(**obj) @@ -482,6 +482,15 @@ def upload_dist(request): return redirect('/admin') +@api_view(['POST']) +def upload_houses(request): + warnings.filterwarnings('ignore') + file_dist = request.FILES['file_houses'] + utils.load_houses(file_dist) + messages.success(request, 'Файл с домами успешно загружен') + return redirect('/admin') + + @api_view(['GET']) @permission_classes([IsAuthenticated]) def get_current_user(request): diff --git a/templates/admin/index.html b/templates/admin/index.html index 5e8721b..93ebb19 100644 --- a/templates/admin/index.html +++ b/templates/admin/index.html @@ -64,6 +64,12 @@ +

Загрузить файл с домами

+
+ {% csrf_token %} + + +
{% endif %}