From 893b762c3ea1dadb7050b9b823da1364f5444cb2 Mon Sep 17 00:00:00 2001 From: Alberto Moreta Date: Mon, 27 May 2024 13:34:13 +0200 Subject: [PATCH] MES-57: Add HG synchronization --- api/client/Assets Links.bru | 11 ++ api/client/HGSync/Fetch Account.bru | 23 +++ api/client/HGSync/Preregister Consumer.bru | 33 ++++ api/client/HGSync/Preregister Intercoop.bru | 34 +++++ api/client/HGSync/Preregister Provider.bru | 44 ++++++ api/serializers/user.py | 10 ++ api/urls.py | 4 + api/views/user.py | 141 ++++++++++++++++++ authentication/models/user.py | 3 + .../management/commands/import_madrid_data.py | 8 +- 10 files changed, 309 insertions(+), 2 deletions(-) create mode 100644 api/client/Assets Links.bru create mode 100644 api/client/HGSync/Fetch Account.bru create mode 100644 api/client/HGSync/Preregister Consumer.bru create mode 100644 api/client/HGSync/Preregister Intercoop.bru create mode 100644 api/client/HGSync/Preregister Provider.bru create mode 100644 api/serializers/user.py create mode 100644 api/views/user.py diff --git a/api/client/Assets Links.bru b/api/client/Assets Links.bru new file mode 100644 index 0000000..f2d4812 --- /dev/null +++ b/api/client/Assets Links.bru @@ -0,0 +1,11 @@ +meta { + name: Assets Links + type: http + seq: 1 +} + +get { + url: {{URL}}/.well-known/assetlinks.json + body: none + auth: none +} diff --git a/api/client/HGSync/Fetch Account.bru b/api/client/HGSync/Fetch Account.bru new file mode 100644 index 0000000..dca8754 --- /dev/null +++ b/api/client/HGSync/Fetch Account.bru @@ -0,0 +1,23 @@ +meta { + name: Fetch Account + type: http + seq: 1 +} + +get { + url: {{URL}}/api/v1/fetch/ + body: json + auth: none +} + +headers { + Authorization: Token {{token}} +} + +body:json { + { + "uuid": "", + "cif": "" , + "email": "" + } +} diff --git a/api/client/HGSync/Preregister Consumer.bru b/api/client/HGSync/Preregister Consumer.bru new file mode 100644 index 0000000..f99c166 --- /dev/null +++ b/api/client/HGSync/Preregister Consumer.bru @@ -0,0 +1,33 @@ +meta { + name: Preregister Consumer + type: http + seq: 3 +} + +post { + url: {{URL}}/api/v1/preregister/ + body: json + auth: none +} + +headers { + Authorization: Token {{token}} +} + +body:json { + { + "person": { + "cif": "1234567A", + "member_id": "1234", + "name": "Prueba", + "surname": "Consumidora", + "email": "", + "contact_phone": "123123456", + "address": "Calle falsa 123", + "city": "MAD" + }, + "email": "" + + + } +} diff --git a/api/client/HGSync/Preregister Intercoop.bru b/api/client/HGSync/Preregister Intercoop.bru new file mode 100644 index 0000000..bb05e66 --- /dev/null +++ b/api/client/HGSync/Preregister Intercoop.bru @@ -0,0 +1,34 @@ +meta { + name: Preregister Intercoop + type: http + seq: 4 +} + +post { + url: {{URL}}/api/v1/preregister/ + body: json + auth: none +} + +headers { + Authorization: Token {{token}} +} + +body:json { + { + "person": { + "cif": "1234567A", + "member_id": "1234", + "name": "Prueba", + "surname": "Intercoop", + "email": "", + "contact_phone": "123123456", + "address": "Calle falsa 123", + "city": "MAD", + "is_intercoop": true + }, + "email": "" + + + } +} diff --git a/api/client/HGSync/Preregister Provider.bru b/api/client/HGSync/Preregister Provider.bru new file mode 100644 index 0000000..c1ebc14 --- /dev/null +++ b/api/client/HGSync/Preregister Provider.bru @@ -0,0 +1,44 @@ +meta { + name: Preregister Provider + type: http + seq: 2 +} + +post { + url: {{URL}}/api/v1/preregister/ + body: json + auth: none +} + +headers { + Authorization: Token {{token}} +} + +body:json { + { + "entity": { + "cif": "1234567A", + "name": "Entidad falsa", + "member_id": "1234", + "description": "Entidad falsa descripción larga", + "short_description": "Entidad falsa descripción corta", + "email": "", + "contact_phone": "123123456", + "address": "Calle falsa 123", + "city" : "MAD", + "latitude": 0, + "longitude": 0, + "legal_form": "cooperativa", + "num_workers": 1, + "telegram_link": "www.telegram.com", + "twitter_link": "www.twitter.com", + "webpage_link": "app.mercadosocial.net", + "facebook_link": "https://www.facebook.com", + "instagram_link": "https://www.instagram.com", + "categories": ["97924fef-a60a-4c9e-adc1-0ce35e0dd8b9", "83d97ae0-538e-43d5-908e-d30b77c4405a"] + }, + "email": "" + + + } +} diff --git a/api/serializers/user.py b/api/serializers/user.py new file mode 100644 index 0000000..1a46851 --- /dev/null +++ b/api/serializers/user.py @@ -0,0 +1,10 @@ +from rest_framework import serializers + +from authentication.models import User + + +class UserSerializer(serializers.ModelSerializer): + + class Meta: + model = User + exclude = ["id", "password", "is_staff", "is_superuser"] \ No newline at end of file diff --git a/api/urls.py b/api/urls.py index bb12d62..7112b57 100644 --- a/api/urls.py +++ b/api/urls.py @@ -10,6 +10,7 @@ from api.views.news import NewsViewSet from api.views.offers import OffersViewSet from api.views.provider import EntitiesView +from api.views.user import FetchUserView, PreRegisterUserView router = DefaultRouter() router.register("devices", FCMDeviceAuthorizedViewSet) @@ -29,6 +30,9 @@ re_path(r"v2/nodes/(?P\d+)/consumer/", ConsumerViewSet.as_view()), path("v1/entities/", EntitiesView.as_view()), + path("v1/fetch/", FetchUserView.as_view()), + path("v1/preregister/", PreRegisterUserView.as_view()) + ] diff --git a/api/views/user.py b/api/views/user.py new file mode 100644 index 0000000..ed12df0 --- /dev/null +++ b/api/views/user.py @@ -0,0 +1,141 @@ + +from django.core.exceptions import MultipleObjectsReturned +from django.http import HttpResponse, HttpResponseNotFound, JsonResponse, HttpResponseForbidden +from rest_framework import authentication, status +from rest_framework.permissions import IsAuthenticated, IsAdminUser +from rest_framework.response import Response +from rest_framework.views import APIView + +from api.serializers.consumer import ConsumerSerializer +from api.serializers.provider import ProviderSerializer +from api.serializers.user import UserSerializer +from authentication.models import User +from authentication.models.api_token import APIToken +from authentication.models.preregister import PreRegisteredUser +from market.management.commands.import_madrid_data import set_social_profiles, set_categories +from market.models import Account, Provider, Consumer, Category +from django.utils.translation import gettext_lazy as _ + + +class FetchUserView(APIView): + authentication_classes = [authentication.TokenAuthentication] + permission_classes = (IsAuthenticated, IsAdminUser) + + def get(self, request, format=None): + + + data = request.data + + instance = None + if 'uuid' in data: + instance = Account.objects.get(id=data['uuid']) + if instance is None and 'cif' in data and data['cif'] is not None: + try: + instance = Account.objects.get(cif=data['cif']) + except MultipleObjectsReturned: + raise Exception(f"Duplicated person. CIF: {data['cif']}. ") + if instance is None and 'email' in data and data['email'] is not None: + try: + instance = Account.objects.get(email=data['email']) + except MultipleObjectsReturned: + raise Exception(f"Duplicated person. Email: {data['email']}") + if instance is None: + return HttpResponseNotFound() + + if instance.node != request.user.node: + return HttpResponseForbidden() + + response = {"api_key": APIToken.objects.get_or_create(user=instance.owner)[0].key} + if isinstance(instance, Consumer): + response['type'] = "person" + response['person'] = ConsumerSerializer(instance).data + if (response['person'] is not None) and 'owner' in response['person']: + response['person']['id'] = instance.id + del response["person"]["owner"] + + response['person']['profile_image'] = instance.profile_image.url if instance.profile_image else None + + if response['person']['favorites']: + for i, uuid in enumerate(response['person']['favorites']): + response['person']['favorites'][i] = uuid + elif isinstance(instance, Provider): + response['type'] = "entity" + response['entity'] = ProviderSerializer(instance).data + if (response['entity'] is not None) and 'user' in response['entity']: + response['entity']['id'] = instance.id + if response['entity']['logo']: + response['entity']['logo'] = instance.profile_image.url if instance.profile_image else None + del response['entity']['user'] + del response['entity']['gallery'] + + if instance.categories.count() > 0: + response['entity']['categories'] = [] + for cat in instance.categories.all(): + response['entity']['categories'].append(cat.pk) + + response['user'] = UserSerializer(instance.owner).data + response['user']['is_registered'] = instance.owner.is_registered() + + return Response(data=response, status=status.HTTP_200_OK) + + +class PreRegisterUserView(APIView): + authentication_classes = [authentication.TokenAuthentication] + permission_classes = (IsAuthenticated, IsAdminUser) + + def post(self, request, *args, **kwargs): + data = request.data + + account = None + email = data['email'] + + if not request.user.node: + return HttpResponse(_("Este usuario no gestiona ningún mercado."), status=400) + + if User.objects.filter(email=email).exists(): + return HttpResponse(_("Ya existe un usuario registrado con este correo electrónico."), status=400) + + result = {} + if 'person' in data: + consumer = data['person'] + account = Consumer.objects.create( + node=request.user.node, + cif=consumer.get('cif'), + email=email, + member_id=consumer.get('member_id'), + first_name=consumer.get('name'), + last_name=consumer.get('surname'), + address=consumer.get('address'), + city=consumer.get('city'), + phone_number=consumer.get('contact_phone'), + is_intercoop=consumer.get('is_intercoop', False) + ) + result = {"person": {"id": account.id}} + elif 'entity' in data: + provider = data['entity'] + account = Provider.objects.create( + node=request.user.node, + cif=provider.get('cif'), + email=email, + member_id=provider.get('member_id'), + name=provider.get('name'), + address=provider.get('address'), + city=provider.get('city'), + description=provider.get('description'), + short_description=provider.get('short_description'), + latitude=provider.get('latitude', 0), + longitude=provider.get('longitude', 0), + num_workers=provider.get('num_workers', 1), + legal_form=provider.get('legal_form'), + webpage_link=provider.get('webpage_link'), + phone_number=provider.get('contact_phone'), + ) + set_social_profiles(provider, account) + set_categories(provider, account) + + result = {"entity": {"id": account.id}} + else: + return HttpResponse(_("No existe objeto entity o person"), status=400) + + PreRegisteredUser.create_user_and_preregister(account) + return JsonResponse(result, status=200) diff --git a/authentication/models/user.py b/authentication/models/user.py index 686a890..17c0eb0 100644 --- a/authentication/models/user.py +++ b/authentication/models/user.py @@ -82,6 +82,9 @@ def __str__(self): def is_preregistered(self): return self.preregister.all().count() > 0 + def is_registered(self): + return self.preregister.count() == 0 + @property def display_name(self): return self.first_name or self.email diff --git a/market/management/commands/import_madrid_data.py b/market/management/commands/import_madrid_data.py index e4900fc..94997d3 100644 --- a/market/management/commands/import_madrid_data.py +++ b/market/management/commands/import_madrid_data.py @@ -133,6 +133,11 @@ def set_social_profiles(provider_data, provider_instance): ProviderSocialProfile.objects.create(social_network=social_network, url=url, provider=provider_instance) +def set_categories(provider_data, provider_instance): + if 'categories' in provider_data and provider_data['categories']: + provider_instance.categories.set(Category.objects.filter(pk__in=provider_data['categories'])) + + def set_offers(provider_data, provider_instance): for offer in provider_data['offers']: @@ -260,8 +265,7 @@ def import_providers(providers, node): provider_created.profile_image.name = item['logo'] - if item['categories']: - provider_created.categories.set(Category.objects.filter(id__in=item['categories'])) + set_categories(item, provider_created) provider_created.save()