2023-11-09 18:47:11 +01:00

1232 lines
47 KiB
Python

#from django.shortcuts import render
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework import status
from django.conf import settings
from django.http import HttpResponse
from django.shortcuts import render
from django.db.models import Count, F, Sum
from django.core.files import File
from django.core.files.temp import NamedTemporaryFile
import magic
from datetime import datetime
from time import mktime
import os
import uuid
import tempfile
import requests, json
import cv2
import imutils
import openfoodfacts
import base64
from django_q.tasks import async_task
from .models import *
from .serializers import *
# Create your views here.
@api_view(['GET', 'POST'])
def purchase_list(request):
if request.method == 'GET':
data = Purchase.objects.all().order_by('purchase_date')
serializer = PurchaseSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PurchaseSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['PUT', 'DELETE'])
def purchases_detail(request, pk):
try:
purchase = Purchase.objects.get(pk=pk)
except Purchase.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'PUT':
print(request.data['data'])
serializer = PurchaseSerializerDepth(purchase, data=request.data['data'],context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
purchase.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET','POST'])
def purchase_articles(request, pk):
try:
purchaseArticles = PurchaseArticle.objects.filter(purchase_id=pk)
except PurchaseArticle.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
#print(purchaseArticles)
serializer = PurchaseArticlesSerializer(purchaseArticles, context={'request': request}, many=True)
return Response(serializer.data)
#Add existing article to the current purchase
elif request.method == 'POST':
inputData = request.data['data']
inputData['purchase_id'] = pk
print(inputData)
#If we add a existing article to the current purchase, no map exists for it. Therefore we have to create it.
purchaseImage = Purchase.objects.get(pk=pk).receipeImage
article = Article.objects.get(pk=inputData['article_id']['pk'])
knownArticleMaps = ArticleMaps.objects.filter(article=article).distinct('receipeString')
print(knownArticleMaps)
#a = ArticleMaps.objects.filter(article=article).annotate(count=Count('receipeString', distinct=True)).order_by()
#for element in a:
# print(a[0])
# print(a[1])
#If we have different strings, simply take the first occurence
receipeString = knownArticleMaps[len(knownArticleMaps)-1].receipeString
articleMap = ArticleMaps.objects.create(article=article, receipeImage=purchaseImage, receipeString=receipeString)
print('Serialize data for response')
serializer = PurchaseArticlesSerializer(data=inputData)
if serializer.is_valid():
serializer.save()
respData = serializer.data
return Response(respData, status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
def new_purchase_article(request,pk):
try:
purchase = Purchase.objects.get(pk=pk)
except Purchase.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'POST':
inputData = request.data['data']
# 1. Create first new article
article = Article.objects.create(name=inputData['article_id']['name'],MwSt=inputData['MwSt'])
# 2. Create new PurchaseArticle with the new article in the given purchase
purchaseArticle = PurchaseArticle.objects.create(article_id=article,
purchase_id=purchase,
quantity=int(inputData['quantity']),
price=float(inputData['price']),
inSale=inputData['inSale']
)
# 3. Every combination of purchase and article should have a map, so we create a new one
purchaseImage = Purchase.objects.get(pk=pk).receipeImage
articleMap = ArticleMaps.objects.create(article=article, receipeImage=purchaseImage)
#4. Serialize the new data, for responding
serializer = PurchaseArticlesSerializer(purchaseArticle)
respData = serializer.data
return Response(respData, status=status.HTTP_201_CREATED)
@api_view(['POST'])
def exchange_purchase_article(request):
if request.method == 'POST':
inputData = request.data['data']
print(inputData)
deleteOldArticle = inputData['deleteOld']
newArticle = Article.objects.get(pk=inputData['newArticle']['pk'])
oldArticle = Article.objects.get(pk=inputData['oldRow']['article_id']['pk'])
purchase = Purchase.objects.get(pk=inputData['oldRow']['purchase_id'])
purchaseArticle = PurchaseArticle.objects.get(article_id=oldArticle, purchase_id=purchase)
articleMap = ArticleMaps.objects.get(pk=inputData['oldRow']['map']['pk'])
#Assing new article to purchaseArticle and articleMap
purchaseArticle.article_id = newArticle
purchaseArticle.save()
articleMap.article = newArticle
articleMap.save()
#If the old article is not in use anymore, delete it
purchaseArticle = PurchaseArticle.objects.filter(article_id=oldArticle)
print(purchaseArticle)
if len(purchaseArticle) == 0 and deleteOldArticle:
print('Old article deleted')
oldArticle.delete()
purchaseArticle = PurchaseArticle.objects.get(article_id=newArticle, purchase_id=purchase)
serializer = PurchaseArticlesSerializer(purchaseArticle)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['POST'])
def exchange_purchase_market(request,pk):
try:
purchase = Purchase.objects.get(pk=pk)
except Purchase.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'POST':
inputData = request.data['data']
print(inputData)
deleteOldMarket = inputData['deleteOld']
newMarket = Market.objects.get(pk=inputData['newMarket']['id'])
oldMarket = purchase.market
purchase.market = newMarket
purchase.save()
#If the old market is not in use anymore, delete it
purchaseMarkets = Purchase.objects.filter(market=oldMarket)
if len(purchaseMarkets) == 0 and deleteOldMarket:
print('Old market deleted')
oldMarket.delete()
serializer = PurchaseSerializerDepth(purchase)
return Response(serializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET'])
def article_list(request):
if request.method == 'GET':
data = Article.objects.all().order_by('brand__name')
serializer = ArticleSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
@api_view(['PUT','DELETE'])
def purchaseArticleMod(request, pk):
try:
purchaseArticle = PurchaseArticle.objects.get(pk=pk)
except PurchaseArticle.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'PUT':
print(request.data['newRow'])
data = request.data['newRow']
try:
data['map']['location_x'] = int(data['map']['location_x'])
data['map']['location_y'] = int(data['map']['location_y'])
data['map']['location_w'] = int(data['map']['location_w'])
data['map']['location_h'] = int(data['map']['location_h'])
except TypeError:
data['map']['location_x'] = None
data['map']['location_y'] = None
data['map']['location_w'] = None
data['map']['location_h'] = None
purchaseArticleSerializer = PurchaseArticlesSerializer(purchaseArticle, data=data,context={'request': request})
mapData = ArticleMaps.objects.get(pk=data['map']['pk'])
if data['map']['receipeString'] == '' or data['map']['receipeString'] == None:
data['map']['receipeString'] = mapData.receipeString
mapSerializer = ArticleMapSerzializer(mapData, data=data['map'],context={'request': request} )
if purchaseArticleSerializer.is_valid() and mapSerializer.is_valid():
purchaseArticleSerializer.save()
mapSerializer.save()
article = Article.objects.get(pk=data['article_id']['pk'])
articleDataFromRequest = data['article_id']
if articleDataFromRequest['name'] == '':
articleDataFromRequest['name'] = 'Bitte Namen setzen.'
articleSerializer = ArticleSerializer(article, data=articleDataFromRequest,context={'request': request})
if articleSerializer.is_valid():
articleSerializer.save()
else:
print(articleSerializer.errors)
return Response(articleSerializer.errors, status=status.HTTP_400_BAD_REQUEST)
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(purchaseArticleSerializer.errors)
print(mapSerializer.errors)
return Response(purchaseArticleSerializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
print(purchaseArticle.article_id)
purchasesWithArticle = PurchaseArticle.objects.filter(article_id=purchaseArticle.article_id)
purchase = Purchase.objects.get(pk=purchaseArticle.purchase_id)
articleMap = ArticleMaps.objects.get(article=purchaseArticle.article_id, receipeImage=purchase.receipeImage)
if len(purchasesWithArticle) > 1:
purchaseArticle.delete()
else:
# If the articel is only in the current purchase, we should delete it, to keep the database clean
# If we delete the article, also the map and the purchaseArticel object will be deleted, because
# of cascade option
purchaseArticle.article_id.delete()
articleMap.delete()
# purchaseArticle.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['PUT'])
def articleMapMod(request, pk):
try:
maps = ArticleMaps.objects.get(pk=pk)
except ArticleMaps.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'PUT':
data = request.data['data']
try:
data['location_x'] = int(data['location_x'])
data['location_y'] = int(data['location_y'])
data['location_w'] = int(data['location_w'])
data['location_h'] = int(data['location_h'])
except TypeError:
data['location_x'] = None
data['location_y'] = None
data['location_w'] = None
data['location_h'] = None
if data['receipeString'] == '':
data['receipeString'] = maps.receipeString
print(data)
mapSerializer = ArticleMapSerzializer(maps, data=data,context={'request': request})
if mapSerializer.is_valid():
mapSerializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(mapSerializer.errors)
return Response(mapSerializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET','POST'])
def articleMapStrings_list(request):
if request.method == 'GET':
data = ReceipeString.objects.all()
serializer = ReceipeStringSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = ReceipeStringSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def market_list(request):
if request.method == 'GET':
data = Market.objects.all()
serializer = MarketSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = MarketSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET','PUT', 'DELETE'])
def markets_detail(request, pk):
try:
market = Market.objects.get(pk=pk)
except Market.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = MarketSerializer(market, context={'request': request}, many=False)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = MarketSerializer(market, data=request.data,context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
market.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET','PUT', 'DELETE'])
def article_detail(request, pk):
try:
article = Article.objects.get(pk=pk)
except Article.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = ArticleSerializer(article, context={'request': request}, many=False)
return Response(serializer.data)
elif request.method == 'PUT':
print(request.data['article'])
serializer = ArticleSerializer(article, data=request.data['article'],context={'request': request},many=False)
if serializer.is_valid():
print(serializer.errors)
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
article.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET','PUT','POST','DELETE'])
def articleArticlePackaging(request, pk):
try:
articlePackages = PackagingArticle.objects.filter(article_id=pk)
except PackagingArticle.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = PackagingArticleSerializer(articlePackages, context={'request': request}, many=True)
respData = serializer.data
return Response(respData)
elif request.method == 'PUT':
# Hier ist etwas umweg notwendig, da ich nicht weiß, warum er id bzw pk nicht deserialzied bzw. validiert. So bekommt die
# Routine aber nur die zu ändernden Daten.
serializer = PackagingArticleSerializer(articlePackages.get(pk=request.data['updatedRow']['id']), data=request.data['updatedRow'],context={'request': request},many=False)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'POST':
serializer = PackagingArticleSerializer(data=request.data['newValue'])
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data,status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
try:
id = int(request.body.decode())
except ValueError:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
articlePackages = PackagingArticle.objects.get(article_id=pk, pk= id)
articlePackages.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET','PUT'])
def articlePackagingValues(request, pk):
packaging = PackagingArticle.objects.filter(article_id=pk)
if request.method == 'GET':
serializer = PackagingArticleSerializer(packaging, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = PackagingArticleSerializer(packaging, data=request.data,context={'request': request},many=False)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view (['GET'])
def articleNutrient_list(request):
if request.method == 'GET':
data = Nutrient.objects.all()
serializer = NutrientSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
@api_view(['GET','PUT','DELETE'])
def articleNutritionalValues(request, pk):
nutriVals = NutrientArticle.objects.filter(article=pk)
if request.method == 'GET':
serializer = NutrientArticleSerializer(nutriVals, context={'request': request}, many=True)
#Serializer data should always contain Makronutrimennts in the right order
#Check if a specific nutrient is in the list, if not, add it with value 0
for element in ['Energie' , 'Fett', 'gesättigte Fettsäuren', 'Kohlenhydrate', 'Zucker', 'Ballaststoffe', 'Eiweiß', 'Salz']:
if not any([element in x for x in serializer.data]):
nutrient = Nutrient.objects.get(name = element)
nutrientSerializer = NutrientSerializer(nutrient, context={'request': request}, many=False)
serializer.data.append([{'id': -1,
'article_id': pk,
'nutrient': nutrientSerializer.data,
'value':0,
'unit':'kJ',
'isEstimated': False
}])
data = serializer.data
print(type(data))
print(serializer.data)
return Response(serializer.data)
elif request.method == 'PUT':
print(request.data['nutriData'])
try:
oldData = NutrientArticle.objects.get(article=pk, nutrient=request.data['nutriData']['nutrient']['id'])
except NutrientArticle.DoesNotExist:
oldData = NutrientArticle.objects.create(article=Article.objects.get(pk=pk),
nutrient=Nutrient.objects.get(pk=request.data['nutriData']['nutrient']['id']))
serializer = NutrientArticleSerializer(oldData, data=request.data['nutriData'],context={'request': request},many=False)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
try:
id = int(request.body.decode())
except ValueError:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
nutriVals = NutrientArticle.objects.get(article=pk, pk=id)
nutriVals.delete()
print(nutriVals)
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['POST'])
def post_receipe(request):
if request.method == 'POST':
print(request.FILES)
if "uploadedFile" in request.FILES and "fileTitle" in request.POST:
fileTitle = request.POST["fileTitle"]
applyBinarize = request.POST["applyBinarize"]
debug = request.POST["debug"]
print(applyBinarize)
print(debug)
uploadedFile = request.FILES["uploadedFile"]
print('Receipe upload complete')
t = int(mktime(datetime.now().timetuple()))
os.makedirs(settings.SCRATCH_DIR, exist_ok=True)
with tempfile.NamedTemporaryFile(prefix="receipe-upload-",
suffix=".jpg",
dir=settings.SCRATCH_DIR,
delete=False) as f:
for chunk in uploadedFile.chunks():
f.write(chunk)
os.utime(f.name, times=(t, t))
temp_filename = f.name
task_id = str(uuid.uuid4())
print("Posting job to queue")
async_task("receipe.tasks.consume_file",
temp_filename,
applyBinarize=applyBinarize,
debug=True,
task_id=task_id,
task_name=os.path.basename(fileTitle)[:100])
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(
status=status.HTTP_400_BAD_REQUEST
)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
def post_articleImage(request, pk):
try:
article = Article.objects.get(pk=pk)
except Article.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'POST':
print(request)
if "uploadedFile" in request.FILES and "fileTitle" in request.POST:
fileTitle = request.POST["fileTitle"]
uploadedFile = request.FILES["uploadedFile"]
print('Article image upload complete')
print(type(uploadedFile))
if fileTitle == 'frontImage':
article.frontImage.delete()
article.frontImage = uploadedFile
elif fileTitle == 'ingredientsImage':
article.ingredientsImage.delete()
article.ingredientsImage = uploadedFile
elif fileTitle == 'nutritionImage':
article.nutritionImage.delete()
article.nutritionImage = uploadedFile
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
article.save()
serializedData = ArticleSerializer(article, context={'request': request}, many=False)
# For visualisation we need the ids of all ancestors, in order to expand the tree. Therefore we fetch the data here
# TODO: Find better place, maybe in a custom serializer...
if serializedData.data['category'] is not None:
id = serializedData.data['category']['id']
node = Category.objects.get(id=id)
ancestors = node.get_ancestors()
ancestorIds = []
for element in ancestors:
ancestorIds.append(element.id)
serializedData.data['category']['ancestorIds'] = ancestorIds
return Response(serializedData.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
#This method seems to be not the fastest and for more user the image should be delivered by a webserver as a static file...
@api_view(['GET'])
def receipeImage(request, pk):
try:
image = ReceipeImage.objects.get(pk=pk)
except image.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
wrapper = image.source_file_trashed.read()
image_data = wrapper
content_type = magic.from_buffer(wrapper, mime=True)
response = HttpResponse(image_data,content_type=content_type)
response['Content-Length'] = os.path.getsize(image.source_path_trashed)
return response
@api_view(['GET'])
def offsearch_get_by_ean(request,ean,pk):
try:
article = Article.objects.get(pk=pk)
except Article.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
search_result = openfoodfacts.products.get_product(ean)
#ean = 4104420017849
#url = "https://world.openfoodfacts.org/api/v0/product/"+str(ean)+".json"
#with requests.Session() as s:
# r = s.get(url)
# print(r.content)
#TODO: Handle wrong EAN / empty result
try:
image_url = search_result['product']['selected_images']['front']['display']['de']
img_data = requests.get(image_url).content
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(img_data)
img_temp.flush()
article.frontImage.delete()
article.frontImage.save(str(pk)+"-front.jpg", File(img_temp), save=True)
except KeyError:
pass
try:
image_url = search_result['product']['selected_images']['ingredients']['display']['de']
img_data = requests.get(image_url).content
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(img_data)
img_temp.flush()
article.ingredientsImage.delete()
article.ingredientsImage.save(str(pk)+"-ingredients.jpg", File(img_temp), save=True)
except KeyError:
pass
try:
image_url = search_result['product']['selected_images']['nutrition']['display']['de']
img_data = requests.get(image_url).content
img_temp = NamedTemporaryFile(delete=True)
img_temp.write(img_data)
img_temp.flush()
article.nutritionImage.delete()
article.nutritionImage.save(str(pk)+"-nutrition.jpg", File(img_temp), save=True)
except KeyError:
pass
if search_result['product']['ecoscore_grade'] == 'unknown':
score = ''
else:
score = search_result['product']['ecoscore_grade']
article.ecoGrade = score.upper()
try:
score = search_result['product']['nova_group']
article.novaGroup = int(score)
except KeyError:
pass
try:
if search_result['product']['nutriscore_grade'] == 'not-applicable':
score = ''
else:
score = search_result['product']['nutriscore_grade']
article.nutritionGrade = score.upper()
except KeyError:
pass
article.save()
keyVal = [['Energie','energy-kj'],
['Fett','fat'],
['gesättigte Fettsäuren','saturated-fat'],
['Kohlenhydrate','carbohydrates'],
['Zucker','sugars'],
['Ballaststoffe','fiber'],
['Eiweiß','proteins'],
['Salz','salt'],
['Natrium','sodium'],
['Vitamin A','vitamin-a'],
['Vitamin B3','vitamin-b3'],
['Vitamin B1','vitamin-b1'],
['Vitamin B2','vitamin-b2'],
['Vitamin B5','vitamin-b5'],
['Vitamin B6','vitamin-b6'],
['Vitamin B7','vitamin-b7'],
['Vitamin B9','vitamin-b9'],
['Vitamin B12','vitamin-b12'],
['Vitamin C','vitamin-c'],
['Vitamin D','vitamin-d'],
['Vitamin E','vitamin-e'],
['Vitamin K','vitamin-k'],
['Kalium','potassium'],
['Kalzium','calcium'],
['Magnesium','magnesium'],
['Eisen','iron'],
['Zink','zinc'],
['Sulfat','sulfat'],
['Chlorid','chlorid'],
['Hydrogencarbonat','hydrogencarbonat'],
['Iod','iodine']
]
for element in keyVal:
try:
nutrient = Nutrient.objects.get(name = element[0])
try:
articleNutrient = NutrientArticle.objects.get(article=article, nutrient=nutrient)
articleNutrient.value = search_result['product']['nutriments'][element[1]]
articleNutrient.unit = search_result['product']['nutriments'][element[1]+'_unit']
articleNutrient.isEstimated = False
articleNutrient.save()
except NutrientArticle.DoesNotExist:
nutrienArticle = NutrientArticle(article=article,
nutrient=nutrient,
value=search_result['product']['nutriments'][element[1]],
unit=search_result['product']['nutriments'][element[1]+'_unit'],
isEstimated=False
)
nutrienArticle.save()
except KeyError:
pass
articleSerializer = ArticleSerializer(article, context={'request': request}, many=False)
return Response(articleSerializer.data, status=status.HTTP_201_CREATED)
@api_view(['GET', 'POST'])
def articleIngrediences_list(request):
if request.method == 'GET':
data = Ingredients.objects.all().order_by("name")
#print(data)
serializer = IngredientsSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
print(request.data['newIngredient'])
serializer = IngredientsSerializer(data=request.data['newIngredient'])
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET','PUT'])
def articleIngredientValues(request, pk):
ingredient = IngredientsArticle.objects.filter(article=pk)
if request.method == 'GET':
serializer = IngredientsArticleSerializer(ingredient, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = IngredientsArticleSerializer(ingredient, data=request.data,context={'request': request},many=False)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET','PUT','POST','DELETE'])
def articleArticleIngrediences(request, pk):
try:
articleIngrediences = IngredientsArticle.objects.filter(article_id=pk).order_by('position')
except IngredientsArticle.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = IngredientsArticleSerializer(articleIngrediences, context={'request': request}, many=True)
respData = serializer.data
return Response(respData)
elif request.method == 'PUT':
# Hier ist etwas umweg notwendig, da ich nicht weiß, warum er id bzw pk nicht deserialzied bzw. validiert. So bekommt die
# Routine aber nur die zu ändernden Daten.
data = request.data['updatedRow']
print(data)
serializer = IngredientsArticleSerializer(articleIngrediences.get(pk=request.data['updatedRow']['id']),
data=data,
context=data['ingredient'],
many=False,
partial= True)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_204_NO_CONTENT)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'POST':
#print(articleIngrediences.last())
try:
newIngredientPosition = articleIngrediences.last().position + 1
except AttributeError:
newIngredientPosition = 1
data = request.data['newValue']
data['position'] = newIngredientPosition
print(data)
serializer = IngredientsArticleSerializer(data=data, partial=True)
if serializer.is_valid():
serializer.save()
return Response(data=serializer.data,status=status.HTTP_201_CREATED)
else:
print(serializer.errors)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
elif request.method == 'DELETE':
try:
id = int(request.body.decode())
except ValueError:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
articleIngredience = IngredientsArticle.objects.get(article_id=pk, pk= id)
articleIngredience.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
@api_view(['GET', 'POST'])
def articleAllergenes_list(request):
if request.method == 'GET':
data = Allergenes.objects.all()
serializer = AllergenesSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = AllergenesSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleTraces_list(request):
if request.method == 'GET':
data = Traces.objects.all()
serializer = TracesSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = TracesSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleLabels_list(request):
if request.method == 'GET':
data = Labels.objects.all()
serializer = LabelsSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = LabelsSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articlePackaging_list(request):
if request.method == 'GET':
data = Packaging.objects.all()
serializer = PackagingSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = PackagingSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleBrand_list(request):
if request.method == 'GET':
data = Brand.objects.all()
serializer = BrandSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = BrandSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleEMB_list(request):
if request.method == 'GET':
data = EMBs.objects.all()
serializer = EMBSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = EMBSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleOriginIngredients_list(request):
if request.method == 'GET':
data = OriginIngredients.objects.all()
serializer = OriginIngredientsSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = EMBSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET', 'POST'])
def articleManufacturingPlaces_list(request):
if request.method == 'GET':
data = ManufacturingPlaces.objects.all()
serializer = ManufacturingPlacesSerializer(data, context={'request': request}, many=True)
return Response(serializer.data)
elif request.method == 'POST':
serializer = EMBSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@api_view(['GET'])
def categories_list(request):
if request.method == 'GET':
#data = Category.objects.all()
#serializer = CategorySerializer(data, context={'request': request}, many=True)
treeDict = Category.dump_bulk()
#return Response(serializer.data)
return Response(treeDict[0])
@api_view(['GET'])
def singleCategory(request, pk):
try:
category = Category.objects.get(pk=pk)
except Category.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = CategorySerializer(category, context={'request': request}, many=False)
# For visualisation we need the ids of all ancestors, in order to expand the tree. Therefore we fetch the data here
# TODO: Find better place, maybe in a custom serializer...
# Also copy paste from above ...
data = serializer.data
id = data['id']
ancestors = category.get_ancestors()
ancestorIds = []
for element in ancestors:
ancestorIds.append(element.id)
data['ancestorIds'] = ancestorIds
return Response(data)
@api_view(['POST'])
def categories_default(request):
if request.method == 'POST':
#get = lambda node_id: Category.objects.get(pk=node_id)
#root = Category.add_root(name='Artikel')
#node = get(root.pk).add_child(name='Lebensmittel')
#Category.dump_bulk()
basepath = os.path.dirname(os.path.abspath(__file__))
with open(basepath+'/categories.json', 'r') as file:
data = [json.load(file)]
# Das hier wirft den Fehler TypeError: Model.save() missing 1 required positional argument: 'self', es wird aber in die Datenbank geschrieben, von daher fange ich einfach den Fehler und
# hoffe es geht alles gut xD
try:
Category.load_bulk(data, None, keep_ids=True)
Category.save()
except TypeError:
pass
return Response(status=status.HTTP_201_CREATED)
#----------------------------------------------------------------------------------------------------------------------
# --------------------- Scanner API calls -----------------------------------------------------------------------------
@api_view(['POST'])
def receiveImageFromScanner(request):
if request.method == 'POST':
if "uploadedFile" in request.FILES:
uploadedFile = request.FILES["uploadedFile"]
print('[Info] Received upload from scanner.')
print(uploadedFile)
os.makedirs(settings.SCRATCH_DIR, exist_ok=True)
os.makedirs(settings.SCRATCH_DIR+'/ScannerUploads/', exist_ok=True)
with tempfile.NamedTemporaryFile(prefix="receipe-upload-",
suffix=".jpg",
dir=settings.SCRATCH_DIR+'/ScannerUploads/',
delete=False) as f:
for chunk in uploadedFile.chunks():
f.write(chunk)
return Response(status=status.HTTP_204_NO_CONTENT)
else:
return Response(
status=status.HTTP_400_BAD_REQUEST
)
else:
return Response(
status=status.HTTP_400_BAD_REQUEST
)
@api_view(['POST'])
def imageFromScannerComplete(request):
if request.method == 'POST':
files = os.listdir(settings.SCRATCH_DIR+'/ScannerUploads/')
files.sort(key=lambda f: os.path.getmtime(os.path.join(settings.SCRATCH_DIR+'/ScannerUploads/',f)))
if len(files) == 0:
return Response(status=status.HTTP_400_BAD_REQUEST)
images = []
for file in files:
image = cv2.imread(os.path.join(settings.SCRATCH_DIR+'/ScannerUploads/',file))
image = cv2.rotate(image, cv2.ROTATE_90_COUNTERCLOCKWISE)
images.append(image)
# initialize OpenCV's image stitcher object and then perform the image stitching
print("[INFO] Stitching images...")
stitcher = cv2.createStitcher() if imutils.is_cv3() else cv2.Stitcher_create()
(statusStiched, stitched) = stitcher.stitch(images)
# if the status is '0', then OpenCV successfully performed image
# stitching
if statusStiched == 0:
stitched = cv2.rotate(stitched, cv2.ROTATE_90_CLOCKWISE)
now = datetime.now()
temp_filename = settings.SCRATCH_DIR+'/scanner-upload-'+now.strftime("%Y-%m-%d_%H-%M")+'.png'
cv2.imwrite(temp_filename, stitched)
#temp_filename = settings.SCRATCH_DIR+'/scanner-upload-2023-07-14_13-40.png'
task_id = str(uuid.uuid4())
print("[Info] Posting job to queue")
async_task("receipe.tasks.consume_file",
temp_filename,
applyBinarize=True,
debug=False,
task_id=task_id,
task_name=os.path.basename(temp_filename)[:100],
scannerFile=True)
print("[INFO] Image saved.")
for file in files:
os.remove(os.path.join(settings.SCRATCH_DIR+'/ScannerUploads/',file))
return Response(status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
@api_view(['POST'])
def imageFromScannerAgain(request):
if request.method == 'POST':
print(request.data)
temp_filename = settings.SCRATCH_DIR+'/'+request.data['filename']
task_id = str(uuid.uuid4())
print("[Info] Posting job to queue")
async_task("receipe.tasks.consume_file",
temp_filename,
applyBinarize=True,
debug=False,
task_id=task_id,
task_name=os.path.basename(temp_filename)[:100],
scannerFile=True)
print("[INFO] Image saved.")
return Response(status=status.HTTP_201_CREATED)
else:
return Response(status=status.HTTP_400_BAD_REQUEST)
#----------------------------------------------------------------------------------------------------------------------
# --------------------- Analyses API calls -----------------------------------------------------------------------------
@api_view(['POST'])
def articleCountForInterval(request):
if request.method == 'POST':
data = request.data['data']
print(data)
#purchases = Purchase.objects.filter(purchase_date__range=[data['fromDate'], data['toDate']])
#print(purchases)
articles = PurchaseArticle.objects.filter(purchase_id__purchase_date__range=[data['fromDate'], data['toDate']])
#articles = articles.order_by('article_id').values('article_id').annotate(count=Count('article_id')).order_by('count')
# Aggregate over quantity field
articles = articles.order_by('article_id').values('article_id').annotate(count=Sum('quantity')).order_by('count')
print(articles.query)
print(articles[0])
for article in articles:
dbarticle = Article.objects.get(pk=article['article_id'])
#dbbrand = Brand(pk=article.brand)
try:
article['article_name'] = dbarticle.brand.name + ' ' + dbarticle.name
except AttributeError:
article['article_name'] = dbarticle.name
return Response(articles)
@api_view(['POST'])
def brandCountForInterval(request):
if request.method == 'POST':
data = request.data['data']
print(data)
# Aggregate brands
brands = PurchaseArticle.objects.filter(purchase_id__purchase_date__range=[data['fromDate'], data['toDate']])
brands = brands.order_by('article_id__brand').values('article_id__brand').annotate(count=Sum('quantity')).order_by('count')
print(brands.query)
print(brands[0])
for brand in brands:
if brand['article_id__brand'] is None:
brand['brand_name'] = 'Keine Marke'
else:
dbbrand = Brand.objects.get(pk=brand['article_id__brand'])
brand['brand_name'] = dbbrand.name
return Response(brands)