From b843537b837b770366739b183031f78ee7c2f456 Mon Sep 17 00:00:00 2001 From: elitonzky Date: Wed, 6 Dec 2023 17:17:03 -0300 Subject: [PATCH] Creates webhook to update vtex products --- marketplace/services/flows/service.py | 3 + .../services/vtex/private/products/service.py | 4 +- .../services/vtex/utils/data_processor.py | 3 + marketplace/settings.py | 1 + marketplace/urls.py | 7 ++- marketplace/webhooks/__init__.py | 0 marketplace/webhooks/urls.py | 5 ++ marketplace/webhooks/vtex/__init__.py | 0 marketplace/webhooks/vtex/product_updates.py | 60 +++++++++++++++++++ marketplace/webhooks/vtex/urls.py | 10 ++++ 10 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 marketplace/webhooks/__init__.py create mode 100644 marketplace/webhooks/urls.py create mode 100644 marketplace/webhooks/vtex/__init__.py create mode 100644 marketplace/webhooks/vtex/product_updates.py create mode 100644 marketplace/webhooks/vtex/urls.py diff --git a/marketplace/services/flows/service.py b/marketplace/services/flows/service.py index 988e928f..ab910d4c 100644 --- a/marketplace/services/flows/service.py +++ b/marketplace/services/flows/service.py @@ -6,3 +6,6 @@ def update_vtex_integration_status(self, project_uuid, user_email, action): return self.client.update_vtex_integration_status( project_uuid, user_email, action ) + + def update_vtex_products(self, products: list): + pass diff --git a/marketplace/services/vtex/private/products/service.py b/marketplace/services/vtex/private/products/service.py index d71574b9..712210c2 100644 --- a/marketplace/services/vtex/private/products/service.py +++ b/marketplace/services/vtex/private/products/service.py @@ -83,10 +83,12 @@ def update_product_info(self, domain, webhook_payload): seller_ids = self.client.list_active_sellers(domain) if price_modified or stock_modified or other_changes: - updated_products = self.data_processor.process_product_data( + updated_products_dto = self.data_processor.process_product_data( [sku_id], seller_ids, self, domain, update_product=True ) + updated_products = DataProcessor.convert_dtos_to_dicts(updated_products_dto) + return updated_products # ================================ diff --git a/marketplace/services/vtex/utils/data_processor.py b/marketplace/services/vtex/utils/data_processor.py index c03d39d6..c38f73b6 100644 --- a/marketplace/services/vtex/utils/data_processor.py +++ b/marketplace/services/vtex/utils/data_processor.py @@ -157,3 +157,6 @@ def generate_csv_file(csv_content: str) -> io.BytesIO: csv_bytes = csv_content.encode("utf-8") csv_memory = io.BytesIO(csv_bytes) return csv_memory + + def convert_dtos_to_dicts(dtos: List[FacebookProductDTO]) -> List[dict]: + return [dataclasses.asdict(dto) for dto in dtos] diff --git a/marketplace/settings.py b/marketplace/settings.py index de5e3deb..c2512fe1 100644 --- a/marketplace/settings.py +++ b/marketplace/settings.py @@ -66,6 +66,7 @@ "marketplace.wpp_templates", "marketplace.event_driven", "marketplace.wpp_products", + "marketplace.webhooks", # installed apps "rest_framework", "storages", diff --git a/marketplace/urls.py b/marketplace/urls.py index b123ac29..7dd68b95 100644 --- a/marketplace/urls.py +++ b/marketplace/urls.py @@ -11,12 +11,17 @@ from marketplace.swagger import view as swagger_view from marketplace.applications import urls as applications_urls from marketplace.interactions import urls as interactions_urls +from marketplace.webhooks import urls as webhooks_urls admin.site.unregister(Group) -api_urls = [path("", include(applications_urls)), path("", include(interactions_urls))] +api_urls = [ + path("", include(applications_urls)), + path("", include(interactions_urls)), + path("", include(webhooks_urls)), +] urlpatterns = [ diff --git a/marketplace/webhooks/__init__.py b/marketplace/webhooks/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/marketplace/webhooks/urls.py b/marketplace/webhooks/urls.py new file mode 100644 index 00000000..b8606c01 --- /dev/null +++ b/marketplace/webhooks/urls.py @@ -0,0 +1,5 @@ +from django.urls import path, include + +urlpatterns = [ + path("webhook/", include("marketplace.webhooks.vtex.urls")), +] diff --git a/marketplace/webhooks/vtex/__init__.py b/marketplace/webhooks/vtex/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/marketplace/webhooks/vtex/product_updates.py b/marketplace/webhooks/vtex/product_updates.py new file mode 100644 index 00000000..9e6e91cc --- /dev/null +++ b/marketplace/webhooks/vtex/product_updates.py @@ -0,0 +1,60 @@ +from rest_framework.views import APIView +from rest_framework.response import Response +from rest_framework import status + +from marketplace.services.vtex.private.products.service import PrivateProductsService +from marketplace.clients.vtex.client import VtexPrivateClient +from marketplace.applications.models import App +from marketplace.services.vtex.exceptions import ( + CredentialsValidationError, + NoVTEXAppConfiguredException, +) +from marketplace.clients.flows.client import FlowsClient +from marketplace.services.flows.service import FlowsService + + +class VtexProductUpdateWebhook(APIView): + flows_client_class = FlowsClient + flows_service_class = FlowsService + vtex_client_class = VtexPrivateClient + vtex_service_class = PrivateProductsService + + def post(self, request, app_uuid): + app = self.get_app(app_uuid) + if not self.can_synchronize(app): + return Response( + {"error": "initial sync not completed"}, + status=status.HTTP_400_BAD_REQUEST, + ) + + domain, app_key, app_token = self.get_credentials_or_raise(app) + vtex_service = self.get_vtex_service(app_key, app_token) + + products_updated = vtex_service.update_product_info(domain, request.data) + self.send_products_to_flows(products_updated) + return Response(status=status.HTTP_200_OK) + + def get_app(self, app_uuid): + try: + return App.objects.get(uuid=app_uuid, configured=True, code="vtex") + except App.DoesNotExist: + raise NoVTEXAppConfiguredException() + + def can_synchronize(self, app): + return app.config.get("initial_sync_completed", False) + + def get_credentials_or_raise(self, app): + domain = app.config["api_credentials"]["domain"] + app_key = app.config["api_credentials"]["app_key"] + app_token = app.config["api_credentials"]["app_token"] + if not domain or not app_key or not app_token: + raise CredentialsValidationError() + return domain, app_key, app_token + + def get_vtex_service(self, app_key, app_token): + client = self.vtex_client_class(app_key, app_token) + return self.vtex_service_class(client) + + def send_products_to_flows(self, products): + flows_service = self.flows_service_class(self.flows_client_class()) + flows_service.update_vtex_products(products) diff --git a/marketplace/webhooks/vtex/urls.py b/marketplace/webhooks/vtex/urls.py new file mode 100644 index 00000000..2980240f --- /dev/null +++ b/marketplace/webhooks/vtex/urls.py @@ -0,0 +1,10 @@ +from django.urls import path +from .product_updates import VtexProductUpdateWebhook + +urlpatterns = [ + path( + "vtex//products-update/api/notification/", + VtexProductUpdateWebhook.as_view(), + name="vtex-product-updates", + ), +]