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

838 lines
30 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Apr 24 14:32:15 2022
@author: elena
"""
from django.db.utils import IntegrityError
from rest_framework import serializers
from .models import *
class MarketSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = Market
fields = ('id','name', 'street', 'street_number', 'zip_code', 'city', 'phone','articles','created','modified')
def pk(self, obj):
return obj.pk
class ReceipeImageSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = Market
fields = ('id','pk')
def pk(self, obj):
return obj.pk
class PurchaseSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
purchase_date = serializers.DateField()
payment_type = serializers.CharField(max_length=20)
total_price = serializers.DecimalField(max_digits=7,decimal_places=2)
market = MarketSerializer()
edit_finished = serializers.BooleanField()
receipeImage = ReceipeImageSerializer()
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Purchase` instance, given the validated data.
"""
try:
return Purchase.objects.create(**validated_data)
except IntegrityError:
return Purchase.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Purchase` instance, given the validated data.
"""
instance.purchase_date = validated_data.get('purchase_date', instance.purchase_date)
instance.save()
return instance
'''
class PurchaseSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = Purchase
fields = ('id','purchase_date', 'payment_type', 'total_price', 'articles', 'market', 'created','modified','receipeImage','edit_finished')
depth = 0
def pk(self, obj):
return obj.pk
'''
class PurchaseSerializerDepth(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = Purchase
fields = ('id','purchase_date', 'payment_type', 'total_price', 'articles', 'market', 'created','modified','receipeImage','edit_finished')
depth = 1
def pk(self, obj):
return obj.pk
class NutritionalValuesSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = NutritionalValues
fields = '__all__'
def pk(self, obj):
return obj.pk
class ReceipeStringSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
class Meta:
model = ReceipeString
fields = '__all__'
def pk(self, obj):
return obj.pk
class ArticleMapSerzializer(serializers.ModelSerializer):
class Meta:
model = ArticleMaps
fields = ('pk','receipeString','location_x','location_y','location_h','location_w')
depth = 1
class CategorySerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=30)
path = serializers.CharField(max_length=255)
depth = serializers.IntegerField()
numchild = serializers.IntegerField()
ancestorIds = serializers.SerializerMethodField()
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Category` instance, given the validated data.
"""
try:
return Category.objects.create(**validated_data)
except IntegrityError:
return Category.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Category` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
# For visualisation we need the ids of all ancestors, in order to expand the tree. Therefore we fetch the data here
def get_ancestorIds(self, obj):
ancestors = obj.get_ancestors()
ids = []
for element in ancestors:
ids.append(element.id)
return ids
class AllergenesSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Allergenes` instance, given the validated data.
"""
try:
return Allergenes.objects.create(**validated_data)
except IntegrityError:
return Allergenes.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Allergenes` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class TracesSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Traces` instance, given the validated data.
"""
try:
return Traces.objects.create(**validated_data)
except IntegrityError:
return Traces.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Traces` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class RecursiveField(serializers.Serializer):
def to_representation(self, value):
serializer = self.parent.parent.__class__(value, context=self.context)
return serializer.data
class IngredientsSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=100)
allergenes = AllergenesSerializer(allow_null = True, many=True)
vegan = serializers.BooleanField(allow_null = True)
vegetarian = serializers.BooleanField(allow_null = True)
palmoilfree = serializers.BooleanField(allow_null = True)
additive = serializers.BooleanField(allow_null = True)
eNumber = serializers.CharField(max_length=7, allow_null = True, allow_blank=True)
subIngredients = RecursiveField(allow_null= True, many=True)#IngredientsSerializer(allow_null = True, many=True) #serializers.ListField()
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Ingredients` instance, given the validated data.
"""
print("Ingredients:Create")
#print(validated_data)
allergenes = validated_data.pop('allergenes')
subIngredients = validated_data.pop('subIngredients')
print(subIngredients)
allergenes_list = []
subIngredients_list = []
for allergene in allergenes:
allergenes_list.append(Allergenes.objects.get(name=allergene['name']))
for subIngredient in subIngredients:
print(subIngredient)
subIngredients_list.append(Ingredients.objects.get(name=subIngredient['name']))
print(allergenes_list)
try:
newObject = Ingredients.objects.create(**validated_data)
newObject.allergenes.set(allergenes_list)
newObject.subIngredients.set(subIngredients_list)
newObject.save()
print(newObject)
return newObject
except IntegrityError:
return Ingredients.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Ingredients` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
# Validate if subIngredients are given, if not raise error. This is needed, because value is emtpy, therefore we have to access the inital data
def validate_subIngredients(self, value):
print("Ingredients:Validate subIngredients")
print(value)
print(self.context)
#print(self.initial_data)
#print(self.initial_data['subIngredients'])
if not 'subIngredients' in self.context:
self.context['subIngredients'] = []
return self.context['subIngredients']
else:
return self.context['subIngredients']
#IngredientsSerializer.base_fields['subIngredients'] = IngredientsSerializer(allow_null = True, many=True)
class LabelsSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Brand` instance, given the validated data.
"""
print("Labels:Create")
try:
return Labels.objects.create(**validated_data)
except IntegrityError:
return Labels.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
print("Labels:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class PackagingSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Packaging` instance, given the validated data.
"""
print("Packaging:Create")
try:
return Packaging.objects.create(**validated_data)
except IntegrityError:
return Packaging.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Packaging` instance, given the validated data.
"""
print("Labels:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class EMBSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `EMBs` instance, given the validated data.
"""
print("Brand:Create")
try:
return EMBs.objects.create(**validated_data)
except IntegrityError:
return EMBs.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `EMBs` instance, given the validated data.
"""
print("Brand:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class ManufacturingPlacesSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Brand` instance, given the validated data.
"""
print("Brand:Create")
try:
return ManufacturingPlaces.objects.create(**validated_data)
except IntegrityError:
return ManufacturingPlaces.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
print("Brand:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class OriginIngredientsSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Brand` instance, given the validated data.
"""
try:
return OriginIngredients.objects.create(**validated_data)
except IntegrityError:
return OriginIngredients.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
class BrandSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Brand` instance, given the validated data.
"""
print("Brand:Create")
try:
return Brand.objects.create(**validated_data)
except IntegrityError:
return Brand.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Snippet` instance, given the validated data.
"""
print("Brand:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
#def validate_name(self, value):
# print('Validate: name')
# return value
#def validate(self, data):
# print('Validate object: name')
# return data
class ArticleSerializer(serializers.ModelSerializer):
brand = BrandSerializer(allow_null = True)
allergenes = AllergenesSerializer(allow_null = True, many=True)
#ingredients = IngredientsSerializer(allow_null = True, many=True)
traces = TracesSerializer(allow_null = True, many=True)
labels = LabelsSerializer(allow_null = True, many=True)
#packagings = PackagingArticleSerializer(allow_null = True, many=True)
embs = EMBSerializer(allow_null = True, many=True)
manufacturingPlaces = ManufacturingPlacesSerializer(allow_null = True, many=True)
originIngredients = OriginIngredientsSerializer(allow_null = True, many=True)
nutritionImage = serializers.ImageField(read_only = True)
ingredientsImage = serializers.ImageField(read_only = True)
frontImage = serializers.ImageField(read_only = True)
category = CategorySerializer(allow_null = True)
class Meta:
model = Article
fields = ('pk','name','brand','EAN','offlink','category',
'quantityPerPackage','unit','novaGroup','nutritionGrade','ecoGrade',
'MwSt','allergenes','traces','embs','labels',
'manufacturingPlaces','originIngredients',
'created','modified',
'nutritionImage','ingredientsImage', 'frontImage') # 'ingredients',
depth = 1
def update(self, instance, validated_data):
print("update method")
print(validated_data)
article = self.fill_deeper_fields(instance, validated_data)
article.name = validated_data.pop('name')
article.EAN = validated_data.pop('EAN')
article.offlink = validated_data.pop('offlink')
article.quantityPerPackage = validated_data.pop('quantityPerPackage')
article.unit = validated_data.pop('unit')
article.novaGroup = validated_data.pop('novaGroup')
article.nutritionGrade = validated_data.pop('nutritionGrade')
article.ecoGrade = validated_data.pop('ecoGrade')
article.MwSt = validated_data.pop('MwSt')
#print("Article before save")
#print(article.labels.get())
article.save()
return article
def create(self, validated_data):
print('create method')
article = Article.objects.create(**validated_data)
article = self.fill_deeper_fields(article, validated_data)
article.name = validated_data.pop('name')
article.EAN = validated_data.pop('EAN')
article.quantityPerPackage = validated_data.pop('quantityPerPackage')
article.unit = validated_data.pop('unit')
article.novaGroup = validated_data.pop('novaGroup')
article.nutritionGrade = validated_data.pop('nutritionGrade')
article.ecoGrade = validated_data.pop('ecoGrade')
article.MwSt = validated_data.pop('MwSt')
return article
def deserialize_multi_field(self, data_list, model):
elements = []
for data in data_list:
if data != None:
#if model == 'ingredients':
# serializer = IngredientsSerializer(
# data=data
# )
if model == 'allergenes':
serializer = AllergenesSerializer(
data=data
)
elif model == 'traces':
serializer = TracesSerializer(
data=data
)
elif model == 'labels':
serializer = LabelsSerializer(
data=data
)
#elif model == 'packaging':
# serializer = PackagingArticleSerializer(
# data=data
# )
elif model == 'embs':
serializer = EMBSerializer(
data=data
)
elif model == 'manufacturingPlaces':
serializer = ManufacturingPlacesSerializer(
data=data
)
elif model == 'originIngredients':
serializer = OriginIngredientsSerializer(
data=data
)
if serializer.is_valid():
ingredients = serializer.save()
elements.append(ingredients)
else:
elements.append(None)
else:
elements.append(None)
return elements
def fill_deeper_fields(self, article, validated_data):
print(validated_data)
brand_data = validated_data.pop('brand')
if brand_data != None:
serializer = BrandSerializer(
data=brand_data
)
if serializer.is_valid():
brand = serializer.save()
article.brand = brand
else:
article.brand = None
else:
article.brand = None
category_data = validated_data.pop('category')
if category_data != None:
serializer = CategorySerializer(
data=category_data
)
if serializer.is_valid():
category = serializer.save()
article.category = category
else:
article.category = None
else:
article.category = None
#data = validated_data.pop('ingredients')
#elements = self.deserialize_multi_field(data, 'ingredients')
#article.ingredients.set(elements)
data = validated_data.pop('allergenes')
elements = self.deserialize_multi_field(data, 'allergenes')
article.allergenes.set(elements)
data = validated_data.pop('traces')
elements = self.deserialize_multi_field(data, 'traces')
article.traces.set(elements)
data = validated_data.pop('labels')
elements = self.deserialize_multi_field(data, 'labels')
article.labels.set(elements)
#data = validated_data.pop('packaging')
#elements = self.deserialize_multi_field(data, 'packaging')
#article.packaging.set(elements)
data = validated_data.pop('embs')
elements = self.deserialize_multi_field(data, 'embs')
article.embs.set(elements)
data = validated_data.pop('manufacturingPlaces')
elements = self.deserialize_multi_field(data, 'manufacturingPlaces')
article.manufacturingPlaces.set(elements)
data = validated_data.pop('originIngredients')
elements = self.deserialize_multi_field(data, 'originIngredients')
article.originIngredients.set(elements)
return article
# Problem: article_id is not readonly, therefore the serializer checks in validation for existence of article in order to create it, we have to prevent this
class PurchaseArticlesSerializer(serializers.ModelSerializer):
id = serializers.SerializerMethodField('pk')
article_id = ArticleSerializer(read_only=True)
#articleSer = ArticlesSerializer(article)
sum_price = serializers.SerializerMethodField()
map = serializers.SerializerMethodField()
class Meta:
model = PurchaseArticle
fields = ('id','quantity','net_weight','price','inSale','article_id','purchase_id','sum_price','map')
#depth = 2
def pk(self, obj):
return obj.pk
def get_sum_price(self, obj):
return int(obj.quantity) * float(obj.price)
def get_map(self, obj):
purchaseImage = Purchase.objects.get(pk=obj.purchase_id).receipeImage
#print(obj.article_id)
articleMap = ArticleMaps.objects.get(article=obj.article_id, receipeImage=purchaseImage)
print(articleMap)
serializedMap = ArticleMapSerzializer(articleMap, many=False)
return serializedMap.data
def create(self, validated_data):
print('create method of PurchaseArticlesSerializer')
print(validated_data)
#article = Article.objects.get(name=validated_data['article_id']['name'],
# brand=validated_data['article_id']['brand'],
# EAN=validated_data['article_id']['EAN'],
# category=validated_data['article_id']['category'])
articleArticle = PurchaseArticle.objects.create(purchase_id=validated_data.pop('purchase_id'),
article_id=validated_data.pop('article_id'),
quantity= validated_data.pop('quantity'),
price = validated_data.pop('price'),
inSale = validated_data.pop('inSale'))
try:
articleArticle.net_weight = validated_data.pop('net_weight')
except KeyError:
pass
return articleArticle
def to_internal_value(self, data):
article_id = data.get('article_id')
internal_data = super().to_internal_value(data)
try:
article = Article.objects.get(pk=article_id['pk'])
except Article.DoesNotExist:
raise ValidationError(
{'article': ['Invalid article primary key']},
code='invalid',
)
internal_data['article_id'] = article
return internal_data
#Serializer for nutrient model
class NutrientSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk')
pk = serializers.IntegerField(read_only=True)
name = serializers.CharField(max_length=50)
isMacroNutrient = serializers.BooleanField()
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `Nutrient` instance, given the validated data.
"""
#print("Nutrient:Create")
try:
return Nutrient.objects.create(**validated_data)
except IntegrityError:
return Nutrient.objects.get(name=validated_data['name'])
def update(self, instance, validated_data):
"""
Update and return an existing `Nutrient` instance, given the validated data.
"""
#print("Labels:Update")
instance.name = validated_data.get('name', instance.name)
instance.save()
return instance
#Serializer for NutrientArticle model
class NutrientArticleSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk',read_only=False)
pk = serializers.IntegerField(read_only=False)
article_id = serializers.IntegerField(source="article.pk")
nutrient = NutrientSerializer()
value = serializers.DecimalField(max_digits=7, decimal_places=2, allow_null = True)
unit = serializers.CharField(max_length=4,allow_null = True)
isEstimated = serializers.BooleanField(allow_null = True)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `NutrientArticle` instance, given the validated data.
"""
#print("NutrientArticle:Create")
#print(validated_data)
#try:
article = Article.objects.get(pk=validated_data.pop('article')['pk'])
nutrient = Nutrient.objects.get(pk=validated_data.pop('nutrient')['pk'])
return PackagingArticle.objects.create(article=article,
nutrient=nutrient,
value=validated_data.pop('value'),
unit=validated_data.pop('unit'),
isEstimated=validated_data.pop('isEstimated')
)
#except IntegrityError:
# return PackagingArticle.objects.get(article_id=validated_data['article_id'])
def update(self, instance, validated_data):
#print('update method for articlepackaging')
print(validated_data)
print(instance)
print(type(instance))
name = validated_data.pop('nutrient', instance.nutrient)['name']
nutrient = Nutrient.objects.get(name=name)
instance.nutrient = nutrient
instance.value = validated_data.pop('value',instance.value)
instance.unit = validated_data.pop('unit',instance.unit)
instance.isEstimated = validated_data.pop('isEstimated',instance.isEstimated)
instance.save()
return instance
class PackagingArticleSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk',read_only=False)
pk = serializers.IntegerField(read_only=False)
#If we need the whole object:
#article_id = ArticleSerializer()
#otherwise, we just take the article primary key
article_id = serializers.IntegerField(source="article_id.pk")
packaging_id = PackagingSerializer()
weight = serializers.IntegerField()
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `PackagingArticle` instance, given the validated data.
"""
print("PackagingArticle:Create")
print(validated_data)
#try:
article = Article.objects.get(pk=validated_data.pop('article_id')['pk'])
return PackagingArticle.objects.create(article_id=article, weight=validated_data.pop('weight'))
#except IntegrityError:
# return PackagingArticle.objects.get(article_id=validated_data['article_id'])
def update(self, instance, validated_data):
print('update method for articlepackaging')
print(validated_data)
#print(instance.packaging_id)
name = validated_data.pop('packaging_id', instance.packaging_id)['name']
packaging = Packaging.objects.get(name=name)
instance.packaging_id = packaging
instance.weight = validated_data.pop('weight',instance.weight)
instance.save()
return instance
class IngredientsArticleSerializer(serializers.Serializer):
id = serializers.SerializerMethodField('pk',read_only=False)
pk = serializers.IntegerField(read_only=False)
#If we need the whole object:
#article_id = ArticleSerializer()
#otherwise, we just take the article primary key
article = serializers.IntegerField(source="article.pk")
ingredient = IngredientsSerializer()
position = serializers.IntegerField()
percent = serializers.FloatField(allow_null = True)
def pk(self, obj):
return obj.pk
def create(self, validated_data):
"""
Create and return a new `IngredientsArticle` instance, given the validated data.
"""
print("IngredientsArticle:Create")
print(validated_data)
#try:
article = Article.objects.get(pk=validated_data.pop('article')['pk'])
return IngredientsArticle.objects.create(article=article, position=validated_data.pop('position'))
#except IntegrityError:
# return PackagingArticle.objects.get(article_id=validated_data['article_id'])
def update(self, instance, validated_data):
print('update method for articleingredient')
print(validated_data)
#print(instance.packaging_id)
#ingredient_json = validated_data.pop('ingredient', instance.ingredient)
ingredient = Ingredients.objects.get(id=self.initial_data['ingredient']['id'])
instance.ingredient = ingredient
instance.position = validated_data.pop('position',instance.position)
instance.percent = validated_data.pop('percent',instance.percent)
instance.save()
return instance