Browse Source

add stats endpoint

Nikos Atlas 9 months ago
parent
commit
71ec961c3c
3 changed files with 64 additions and 13 deletions
  1. 2 1
      requirements.txt
  2. 48 6
      src/telecaster/Clients/CosmohomeClient.py
  3. 14 6
      src/telecaster/views/CosmohomeView.py

+ 2 - 1
requirements.txt

@@ -43,4 +43,5 @@ urllib3==1.26.8
 djangorestframework-xml==2.0.0
 django-crontab==0.7.1
 dicttoxml==1.7.16
-gunicorn==21.2.0
+gunicorn==21.2.0
+xmltodict==0.13.0

+ 48 - 6
src/telecaster/Clients/CosmohomeClient.py

@@ -1,9 +1,11 @@
 import hashlib
+import json
 import struct
 from collections import defaultdict
 from datetime import datetime
 from functools import lru_cache
 
+import xmltodict
 from dicttoxml import dicttoxml
 from django.conf import settings
 
@@ -111,9 +113,8 @@ class CosmohomeClient(PrestaShopClient):
                     combination,
                     float(product.get('price')) + float(combination.get('price'))
                 ),
-                "Quantity": combination.get('quantity') or serialized_product.get(
-                    'Quantity'),
-
+                "Quantity": combination.get('quantity'),
+                "stock": "Y" if int(combination.get('quantity')) > 0 else "N",
                 "Color": self.get_color(product) or serialized_product.get('Color'),
                 "Size": self.get_size(product) or serialized_product.get('Size'),
             })
@@ -269,7 +270,48 @@ def generate_xml():
     return final_xml
 
 
-def generate_xml_task():
+def generate_xml_task(filepath=None):
+    if not filepath:
+        raise RuntimeError("No filepath provided")
     xml = generate_xml()
-    with open(settings.BASE_DIR / 'artifacts/cosmohome_products.xml', 'w') as file:
-        file.write(xml)
+    with open(filepath, 'w') as file:
+        file.write(xml)
+
+
+def generate_stats(filepath=None):
+    if not filepath:
+        raise RuntimeError("No filepath provided")
+    with open(filepath, 'r') as file:
+        xml_string = file.read()
+
+    data_dict = xmltodict.parse(xml_string)
+    date = data_dict.get('store').get('date')
+    products = data_dict.get('store').get('products').get('product')
+
+    total_products = len(products)
+    total_products_in_stock = len([p for p in products if p.get('stock') == 'Y'])
+    total_products_out_of_stock = len([p for p in products if p.get('stock') == 'N'])
+    duplicate_product_ids_count = total_products - len(set([p.get('productId') for p in products]))
+    duplicate_product_mpn_count = total_products - len(set([p.get('MPN') for p in products]))
+
+    def get_duplicates_by(key, output_key=None):
+        duplicates_by_key = defaultdict(list)
+        for p in products:
+            duplicates_by_key[p.get(key)].append(p.get(output_key) if output_key else p)
+        duplicates_by_key = {k: v for k, v in duplicates_by_key.items() if len(v) > 1}
+        return duplicates_by_key
+
+    duplicates_by_mpn = get_duplicates_by('MPN', "productURL")
+    duplicates_by_product_id = get_duplicates_by('productId', "productURL")
+
+    stats = {
+        "date": date,
+        "total_products": total_products,
+        "total_products_in_stock": total_products_in_stock,
+        "total_products_out_of_stock": total_products_out_of_stock,
+        "duplicate_product_ids_count": duplicate_product_ids_count,
+        "duplicate_product_mpn_count": duplicate_product_mpn_count,
+        "duplicates_by_mpn": duplicates_by_mpn,
+        "duplicates_by_product_id": duplicates_by_product_id,
+    }
+    return stats

+ 14 - 6
src/telecaster/views/CosmohomeView.py

@@ -1,9 +1,9 @@
 from rest_framework import viewsets
 from rest_framework.decorators import action
 from rest_framework.request import Request
-from django.http import HttpResponse
+from django.http import HttpResponse, JsonResponse
 
-from ..Clients.CosmohomeClient import generate_xml_task
+from ..Clients.CosmohomeClient import generate_xml_task, generate_stats
 from django.conf import settings
 
 
@@ -11,17 +11,25 @@ class CosmohomeView(viewsets.ViewSet):
     @classmethod
     @action(methods=['get'], detail=False, url_path='generate/xml')
     def generate_xml(cls, request: Request, *args, **kwargs) -> HttpResponse:
-        final_xml = generate_xml_task()
+        filepath = settings.BASE_DIR / "artifacts/cosmohome_products.xml"
+        final_xml = generate_xml_task(filepath)
         return HttpResponse('ok')
 
+    @classmethod
+    @action(methods=['get'], detail=False, url_path='stats')
+    def generate_xml(cls, request: Request, *args, **kwargs) -> JsonResponse:
+        filepath = settings.BASE_DIR / "artifacts/cosmohome_products.xml"
+        stats = generate_stats(filepath)
+        return JsonResponse(stats)
+
     @classmethod
     @action(methods=['get'], detail=False, url_path='xml')
     def xml(cls, request: Request, *args, **kwargs) -> HttpResponse:
-        file = settings.BASE_DIR / "artifacts/cosmohome_products.xml"
+        filepath = settings.BASE_DIR / "artifacts/cosmohome_products.xml"
         try:
-            with open(file, 'rb') as f:
+            with open(filepath, 'rb') as f:
                 return HttpResponse(f.read(), content_type='text/xml')
         except OSError:
-            print(f"No available {file} file. Please generate one first.")
+            print(f"No available {filepath} file. Please generate one first.")
             pass
         return HttpResponse('No available xml file. Please generate one first.', status=404)