#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)