Files
consumocuidado-server/products/views.py
2021-02-08 14:51:24 +01:00

174 lines
7.1 KiB
Python

import logging
import csv
import datetime
import operator
from functools import reduce
from django.shortcuts import render
from django.conf import settings
from django.core import serializers
from django.db.models import Q
# Create your views here.
from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAdminUser, IsAuthenticated
from rest_framework.decorators import api_view, permission_classes
import requests
from products.models import Product
from products.serializers import ProductSerializer
from companies.models import Company
from history.models import HistorySync
from back_latienda.permissions import IsCreator
logging.basicConfig(
filename='logs/product-load.log',
filemode='w',
format='%(levelname)s:%(message)s',
level=logging.INFO,
)
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
permission_classes = [IsAuthenticatedOrReadOnly, IsCreator]
def perform_create(self, serializer):
serializer.save(creator=self.request.user)
@api_view(['GET',])
@permission_classes([IsAuthenticated,])
def my_products(request):
qs = Product.objects.filter(creator=request.user)
data = serializers.serialize('json', qs)
return Response(data=data)
@api_view(['POST',])
@permission_classes([IsAuthenticated,])
def load_coop_products(request):
"""Read CSV file being received
Parse it to create products for related Company
"""
try:
csv_file = request.FILES['csv_file']
if csv_file.name.endswith('.csv') is not True:
logging.error(f"File {csv_file.name} is not a CSV file")
return Response({"errors":{"details": "File is not CSV type"}})
logging.info(f"Reading contents of {csv_file.name}")
decoded_file = csv_file.read().decode('utf-8').splitlines()
csv_reader = csv.DictReader(decoded_file, delimiter=',')
counter = 0
# get company linked to user
company_qs = Company.objects.filter(creator=request.user)
if company_qs:
company = company_qs.first()
else:
return Response({"errors":{"details": "Your user has no company to add products to"}})
# create historysync instance
history = HistorySync.objects.create(company=company, sync_date=datetime.datetime.now(), quantity=len(decoded_file))
for row in csv_reader:
if '' in (row['nombre-producto'], row['descripcion'], row['precio'], row['categoria']):
logging.error(f"Required data missing: {row}")
continue
try:
# download image references in csv
if row['imagen'].strip() != '':
image_url = row['imagen'].strip()
response = requests.get(image_url, stream=True)
if response.status_code == 200:
path = f"{setting.BASE_DIR}media/{row['nombre-producto'].strip()}.{image.url.split('/')[-1]}"
logging.info(f"Saving product image to: {path}")
new_image = open(path, 'wb')
for chunk in response:
new_image.write(chunk)
new_image.close()
else:
logging.warning(f"Image URL did not work: {image_url}")
new_image = None
else:
new_image = None
# TODO: if tags is empty, auto-generate tags
# assemble instance data
product_data = {
'id': None if row['id'].strip()=='' else row['id'].strip(),
'company': Company.objects.filter(creator=request.user).first(),
'name': row['nombre-producto'].strip(),
'description': row['descripcion'].strip(),
'image': new_image,
'url': row['url'].strip(),
'price': row['precio'].strip(),
'shipping_cost': row['gastos-envio'].strip(),
'shipping_terms': row['cond-envio'].strip(),
'discount': row['descuento'].strip(),
'stock': row['stock'].strip(),
'tags': row['tags'].strip(),
'category': row['categoria'].strip(),
'identifiers': row['identificadores'].strip(),
'history': history,
'creator': request.user,
}
Product.objects.create(**product_data)
logging.info(f"Created Product: {product_data}")
counter += 1
except Exception as e:
logging.error(f"Could not parse {row}")
return Response()
except Exception as e:
return Response({"errors": {"details": str(type(e))}})
@api_view(['GET',]) # include allowed methods
def product_search(request):
"""
Takes a string of data, return relevant products
"""
query_string = request.GET.get('query_string', None)
if query_string is None:
return Response({"errors": {"details": "No query string to parse"}})
try:
# save results
result_set = set()
# split query string into single words
chunks = query_string.split('+')
for chunk in chunks:
# search in name
products = Product.objects.filter(name=chunk)
for item in products:
result_set.add(item)
# search in description
products = Product.objects.filter(description=chunk)
for item in products:
result_set.add(item)
# search in tags
products = Product.objects.filter(tags=chunk)
for item in products:
result_set.add(item)
# search in category
products = Product.objects.filter(category=chunk)
for item in products:
result_set.add(item)
# search in attributes
products = Product.objects.filter(attributes=chunk)
for item in products:
result_set.add(item)
serializer = ProductSerializer(result_set, many=True)
return Response(data=serializer.data)
except Exception as e:
return Response({"errors": {"details": str(type(e))}})