522 lines
18 KiB
Python
522 lines
18 KiB
Python
from rest_framework import serializers
|
|
from django.utils.text import slugify
|
|
|
|
from product import models
|
|
from location import models as location_models
|
|
from tag import models as tag_models
|
|
from establishment import models as establishment_models
|
|
from transfer import models as transfer_models
|
|
from utils.methods import get_point_from_coordinates
|
|
from transfer.mixins import TransferSerializerMixin
|
|
from django.conf import settings
|
|
from functools import reduce
|
|
from gallery.models import Image
|
|
|
|
|
|
class WineColorSerializer(TransferSerializerMixin):
|
|
CATEGORY_LABEL = 'Wine color'
|
|
CATEGORY_INDEX_NAME = slugify(CATEGORY_LABEL)
|
|
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField(allow_null=True)
|
|
order_number = serializers.IntegerField(allow_null=True)
|
|
|
|
class Meta:
|
|
model = tag_models.Tag
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'order_number',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
value = attrs.pop('name')
|
|
attrs['old_id'] = attrs.pop('id', None)
|
|
attrs['label'] = {settings.FALLBACK_LOCALE: value}
|
|
attrs['value'] = slugify(value)
|
|
attrs['priority'] = attrs.pop('order_number')
|
|
attrs['category'] = self.tag_category
|
|
return attrs
|
|
|
|
|
|
class WineTypeSerializer(TransferSerializerMixin):
|
|
CATEGORY_LABEL = 'Sugar content'
|
|
CATEGORY_INDEX_NAME = slugify(CATEGORY_LABEL)
|
|
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField()
|
|
|
|
class Meta:
|
|
model = tag_models.Tag
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
value = attrs.pop('name')
|
|
attrs['old_id'] = attrs.pop('id', None)
|
|
attrs['label'] = {settings.FALLBACK_LOCALE: value}
|
|
attrs['value'] = slugify(value)
|
|
attrs['category'] = self.tag_category
|
|
return attrs
|
|
|
|
|
|
class WineBottlesProducedSerializer(TransferSerializerMixin):
|
|
CATEGORY_LABEL = 'Bottles produced'
|
|
CATEGORY_INDEX_NAME = slugify(CATEGORY_LABEL)
|
|
|
|
bottles_produced = serializers.CharField(allow_null=True)
|
|
|
|
class Meta:
|
|
model = tag_models.Tag
|
|
fields = (
|
|
'bottles_produced',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
value = attrs.pop('bottles_produced')
|
|
parsed_value = self.parsed_value(value)
|
|
attrs['label'] = {settings.FALLBACK_LOCALE: parsed_value}
|
|
attrs['value'] = slugify(parsed_value)
|
|
attrs['category'] = self.tag_category
|
|
return attrs
|
|
|
|
def parsed_value(self, value):
|
|
if value.isdigit():
|
|
return int(value)
|
|
|
|
parted = value.split(' ')
|
|
if len(parted) > 1:
|
|
values = [int(i) for i in parted if i.isdigit()]
|
|
return reduce(lambda a, b: a + b, values)
|
|
|
|
lowered = value.lower()
|
|
if 'magnum' in lowered:
|
|
return 1
|
|
|
|
return 0
|
|
|
|
|
|
class ProductStandardSerializer(TransferSerializerMixin):
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField()
|
|
type = serializers.CharField(allow_null=True)
|
|
longitude = serializers.FloatField(allow_null=True)
|
|
latitude = serializers.FloatField(allow_null=True)
|
|
|
|
class Meta:
|
|
model = models.ProductStandard
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'type',
|
|
'longitude',
|
|
'latitude',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
latitude = attrs.pop('latitude', None)
|
|
longitude = attrs.pop('longitude', None)
|
|
standard_type = attrs.pop('type', None)
|
|
|
|
attrs['coordinates'] = get_point_from_coordinates(latitude, longitude)
|
|
attrs['old_id'] = attrs.get('id')
|
|
attrs['standard_type'] = self.get_standard_type(standard_type)
|
|
return attrs
|
|
|
|
def get_standard_type(self, type: str):
|
|
if type == 'Appellation':
|
|
return models.ProductStandard.APPELLATION
|
|
elif type == 'YardClassification':
|
|
return models.ProductStandard.WINEQUALITY
|
|
elif type == 'WineQuality':
|
|
return models.ProductStandard.YARDCLASSIFICATION
|
|
|
|
|
|
class WineClassificationTypeSerializer(TransferSerializerMixin):
|
|
|
|
name = serializers.CharField()
|
|
|
|
class Meta:
|
|
model = models.ProductClassificationType
|
|
fields = (
|
|
'name',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
attrs['product_type'] = self.wine_type
|
|
return attrs
|
|
|
|
@property
|
|
def wine_type(self):
|
|
qs = models.ProductType.objects.filter(index_name=models.ProductType.WINE)
|
|
if qs.exists():
|
|
return qs.first()
|
|
|
|
|
|
class ProductClassificationSerializer(TransferSerializerMixin):
|
|
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField()
|
|
possible_type_id = serializers.IntegerField(allow_null=True)
|
|
possible_color_id = serializers.IntegerField(allow_null=True)
|
|
parent_id = serializers.IntegerField(allow_null=True)
|
|
|
|
class Meta:
|
|
model = models.ProductClassification
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'possible_type_id',
|
|
'possible_color_id',
|
|
'parent_id',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
classification_name = attrs.pop('name')
|
|
possible_type_id = attrs.pop('possible_type_id', None)
|
|
possible_color_id = attrs.pop('possible_color_id', None)
|
|
parent_id = attrs.pop('parent_id', None)
|
|
|
|
attrs['old_id'] = attrs.pop('id')
|
|
attrs['classification_type'] = self.get_classification_type(classification_name)
|
|
attrs['possible_subtype_tag'] = self.get_possible_type_tag(possible_type_id)
|
|
attrs['possible_color_tag'] = self.get_possible_color_tag(possible_color_id)
|
|
attrs['standard'] = self.get_wine_standard(parent_id)
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
possible_color_tag = validated_data.pop('possible_color_tag', None)
|
|
possible_subtype_tag = validated_data.pop('possible_subtype_tag', None)
|
|
obj, _ = self.Meta.model.objects.get_or_create(**validated_data)
|
|
if possible_color_tag:
|
|
obj.tags.add(possible_color_tag)
|
|
if possible_subtype_tag:
|
|
obj.tags.add(possible_subtype_tag)
|
|
return obj
|
|
|
|
def get_classification_type(self, classification_name):
|
|
qs = models.ProductClassificationType.objects.filter(name__icontains=classification_name)
|
|
if qs.exists():
|
|
return qs.first()
|
|
|
|
def get_possible_type_tag(self, possible_type_id):
|
|
if possible_type_id:
|
|
qs = tag_models.Tag.objects.filter(
|
|
old_id=possible_type_id,
|
|
category__index_name=WineTypeSerializer.CATEGORY_INDEX_NAME)
|
|
if qs.exists():
|
|
return qs.first()
|
|
else:
|
|
import ipdb; ipdb.set_trace()
|
|
|
|
def get_possible_color_tag(self, possible_color_id):
|
|
if possible_color_id:
|
|
qs = tag_models.Tag.objects.filter(
|
|
old_id=possible_color_id,
|
|
category__index_name=WineColorSerializer.CATEGORY_INDEX_NAME)
|
|
if qs.exists():
|
|
return qs.first()
|
|
|
|
def get_wine_standard(self, parent_id):
|
|
if parent_id:
|
|
qs = models.ProductStandard.objects.filter(old_id=parent_id)
|
|
if qs.exists():
|
|
return qs.first()
|
|
|
|
|
|
class ProductSerializer(TransferSerializerMixin):
|
|
|
|
establishment_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.Establishments.objects.all(),
|
|
allow_null=True)
|
|
classification_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.ProductClassification.objects.all(),
|
|
allow_null=True)
|
|
wine_region_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.WineLocations.objects.all(),
|
|
allow_null=True)
|
|
wine_type_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.WineType.objects.all(),
|
|
allow_null=True)
|
|
wine_color_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.WineColor.objects.all(),
|
|
allow_null=True)
|
|
appellation_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.ProductClassification.objects.all(),
|
|
allow_null=True)
|
|
village_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.WineLocations.objects.all(),
|
|
allow_null=True)
|
|
# same as wine_village
|
|
# vineyard_id = serializers.PrimaryKeyRelatedField(
|
|
# queryset=transfer_models.WineLocations.objects.all(),
|
|
# allow_null=True)
|
|
wine_quality_id = serializers.PrimaryKeyRelatedField(
|
|
queryset=transfer_models.ProductClassification.objects.all(),
|
|
allow_null=True)
|
|
|
|
# same as establishment name
|
|
id = serializers.IntegerField()
|
|
brand = serializers.CharField(allow_null=True, allow_blank=True)
|
|
name = serializers.CharField(allow_null=True, allow_blank=True)
|
|
vintage = serializers.CharField(allow_null=True)
|
|
type = serializers.CharField(allow_null=True)
|
|
wine_sub_region_id = serializers.CharField(allow_null=True)
|
|
state = serializers.CharField()
|
|
bottles_produced = serializers.CharField(allow_null=True, allow_blank=True)
|
|
unique_key = serializers.CharField(allow_null=True)
|
|
|
|
class Meta:
|
|
model = models.Product
|
|
fields = (
|
|
'id',
|
|
'establishment_id', # done
|
|
'classification_id', # done
|
|
'wine_region_id', # done
|
|
'wine_type_id', # done
|
|
'wine_color_id', # done
|
|
'appellation_id', # done
|
|
'village_id', # done
|
|
# 'vineyard_id',
|
|
'wine_quality_id', # done
|
|
'brand',
|
|
'name', # done
|
|
'vintage', # done
|
|
'type', # done
|
|
'wine_sub_region_id', # done
|
|
'state', # done
|
|
'bottles_produced', # done
|
|
'unique_key', # done
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
name = attrs.pop('name', None)
|
|
establishment = attrs.pop('establishment_id', None)
|
|
brand = attrs.pop('brand', None)
|
|
classification = attrs.pop('classification_id', None)
|
|
vintage = attrs.pop('vintage', None)
|
|
product_type = attrs.pop('type')
|
|
wine_region = attrs.pop('wine_region_id', None)
|
|
wine_sub_region_id = attrs.pop('wine_sub_region_id', None)
|
|
bottles_produced = attrs.pop('bottles_produced', None)
|
|
wine_type = attrs.pop('wine_type_id', None)
|
|
wine_color = attrs.pop('wine_color_id', None)
|
|
appellation = attrs.pop('appellation_id', None)
|
|
village = attrs.pop('village_id', None)
|
|
wine_quality = attrs.pop('wine_quality_id', None)
|
|
name = self.get_name(name, brand)
|
|
old_id = attrs.pop('id')
|
|
state = self.get_state(attrs.pop('state', None))
|
|
|
|
attrs['old_id'] = old_id
|
|
attrs['name'] = name
|
|
attrs['old_unique_key'] = attrs.pop('unique_key')
|
|
attrs['establishment'] = self.get_establishment(establishment)
|
|
attrs['state'] = state
|
|
# attrs['brand'] = self.get_brand(brand)
|
|
attrs['wine_classification'] = self.get_wine_classification(classification)
|
|
attrs['wine_quality'] = self.get_wine_standard(wine_quality,
|
|
models.ProductStandard.WINEQUALITY)
|
|
attrs['wine_appellation'] = self.get_wine_standard(appellation,
|
|
models.ProductStandard.APPELLATION)
|
|
attrs['product_type'] = self.get_product_type(product_type)
|
|
attrs['vintage'] = self.get_vintage_year(vintage)
|
|
attrs['wine_region'] = self.get_wine_region(wine_region)
|
|
attrs['wine_sub_region'] = self.get_wine_sub_region(wine_sub_region_id)
|
|
attrs['bottles_produced_tag'] = self.get_tag(bottles_produced,
|
|
WineBottlesProducedSerializer.CATEGORY_INDEX_NAME)
|
|
attrs['wine_type_tag'] = self.get_tag(wine_type,
|
|
WineTypeSerializer.CATEGORY_INDEX_NAME)
|
|
attrs['wine_color_tag'] = self.get_tag(wine_color,
|
|
WineColorSerializer.CATEGORY_INDEX_NAME)
|
|
attrs['wine_village'] = self.get_wine_village(village)
|
|
attrs['available'] = self.get_availability(state)
|
|
attrs['slug'] = self.get_slug(name, old_id)
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
qs = self.Meta.model.objects.filter(old_id=validated_data.get('old_id'))
|
|
# classifications
|
|
classifications = [validated_data.pop('wine_classification', None)]
|
|
# standards
|
|
standards = [validated_data.pop('wine_quality', None),
|
|
validated_data.pop('wine_appellation', None)]
|
|
# tags
|
|
tags = [validated_data.pop('bottles_produced_tag', None),
|
|
validated_data.pop('wine_type_tag', None),
|
|
validated_data.pop('wine_color_tag', None)]
|
|
|
|
if not qs.exists():
|
|
obj = super().create(validated_data)
|
|
else:
|
|
obj = qs.first()
|
|
|
|
# adding classification
|
|
obj.classifications.add(*[i for i in classifications if i])
|
|
# adding standard
|
|
obj.standards.add(*[i for i in standards if i])
|
|
# adding tags
|
|
obj.tags.add(*[i for i in tags if i])
|
|
return obj
|
|
|
|
def get_name(self, name, brand):
|
|
if name:
|
|
return name
|
|
if brand and not name:
|
|
return brand
|
|
|
|
def get_establishment(self, establishment):
|
|
if establishment:
|
|
qs = establishment_models.Establishment.objects.filter(
|
|
old_id=establishment.id)
|
|
if qs.exists():
|
|
return qs.first()
|
|
|
|
def get_state(self, state):
|
|
if state == 'published':
|
|
return models.Product.PUBLISHED
|
|
elif state == 'out_of_production':
|
|
return models.Product.OUT_OF_PRODUCTION
|
|
return models.Product.WAITING
|
|
|
|
def get_wine_classification(self, classification):
|
|
if classification:
|
|
classification_qs = models.ProductClassification.objects.filter(
|
|
old_id=classification.id)
|
|
if classification_qs.exists():
|
|
return classification_qs.first()
|
|
|
|
def get_wine_region(self, wine_region):
|
|
if wine_region:
|
|
wine_region_qs = location_models.WineRegion.objects.filter(
|
|
old_id=wine_region.id)
|
|
if wine_region_qs.exists():
|
|
return wine_region_qs.first()
|
|
|
|
def get_wine_sub_region(self, wine_sub_region_id):
|
|
if wine_sub_region_id:
|
|
sub_region_qs = location_models.WineSubRegion.objects.filter(
|
|
old_id=wine_sub_region_id)
|
|
if sub_region_qs.exists():
|
|
return sub_region_qs.first()
|
|
|
|
def get_wine_village(self, village):
|
|
if village:
|
|
village_qs = location_models.WineVillage.objects.filter(
|
|
old_id=village.id)
|
|
if village_qs.exists():
|
|
return village_qs.first()
|
|
|
|
def get_tag(self, tag, category_index_name: str):
|
|
tag = tag.name if hasattr(tag, 'name') else tag
|
|
if tag:
|
|
qs = tag_models.Tag.objects.filter(
|
|
value=tag,
|
|
category__index_name=category_index_name)
|
|
if qs.exists():
|
|
return qs.first()
|
|
else:
|
|
import ipdb;ipdb.set_trace()
|
|
|
|
def get_wine_standard(self, standard, standard_type):
|
|
if standard:
|
|
if isinstance(standard, transfer_models.ProductClassification):
|
|
standard = standard.id
|
|
standard_qs = models.ProductStandard.objects.filter(
|
|
standard_type=standard_type,
|
|
old_id=standard)
|
|
if standard_qs.exists():
|
|
return standard_qs.first()
|
|
|
|
def get_availability(self, state: int):
|
|
if state == models.Product.PUBLISHED:
|
|
return True
|
|
return False
|
|
|
|
|
|
class PlateSerializer(TransferSerializerMixin):
|
|
|
|
PRODUCT_TYPE_INDEX_NAME = 'souvenir'
|
|
PRODUCT_SUB_TYPE_INDEX_NAME = 'plate'
|
|
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField()
|
|
vintage = serializers.CharField()
|
|
|
|
class Meta(ProductSerializer.Meta):
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'vintage',
|
|
)
|
|
|
|
def validate(self, attrs):
|
|
old_id = attrs.pop('id')
|
|
name = attrs.get('name')
|
|
product_type = self.get_product_type(self.PRODUCT_TYPE_INDEX_NAME)
|
|
|
|
attrs['old_id'] = old_id
|
|
attrs['vintage'] = self.get_vintage_year(attrs.pop('vintage'))
|
|
attrs['product_type'] = product_type
|
|
attrs['state'] = self.Meta.model.PUBLISHED
|
|
attrs['subtype'] = self.get_product_sub_type(product_type,
|
|
self.PRODUCT_SUB_TYPE_INDEX_NAME)
|
|
attrs['slug'] = self.get_slug(name, old_id)
|
|
return attrs
|
|
|
|
def create(self, validated_data):
|
|
qs = self.Meta.model.objects.filter(old_id=validated_data.get('old_id'))
|
|
# subtypes
|
|
subtypes = [validated_data.pop('subtype', None)]
|
|
|
|
if not qs.exists():
|
|
obj = super().create(validated_data)
|
|
else:
|
|
obj = qs.first()
|
|
|
|
# adding classification
|
|
obj.subtypes.add(*[i for i in subtypes if i])
|
|
return obj
|
|
|
|
|
|
class PlateImageSerializer(serializers.ModelSerializer):
|
|
|
|
id = serializers.IntegerField()
|
|
name = serializers.CharField()
|
|
attachment_suffix_url = serializers.CharField()
|
|
|
|
class Meta:
|
|
model = models.ProductGallery
|
|
fields = (
|
|
'id',
|
|
'name',
|
|
'attachment_suffix_url',
|
|
)
|
|
|
|
def create(self, validated_data):
|
|
image = self.get_image(validated_data.pop('attachment_suffix_url', None),
|
|
validated_data.pop('name', None))
|
|
product = self.get_product(validated_data.pop('id'))
|
|
|
|
if product and image:
|
|
obj, created = models.ProductGallery.objects.get_or_create(
|
|
product=product,
|
|
image=image,
|
|
is_main=True)
|
|
return obj
|
|
|
|
def get_image(self, image_url, name):
|
|
if image_url:
|
|
obj, created = Image.objects.get_or_create(
|
|
title=name,
|
|
image=image_url)
|
|
return obj if created else None
|
|
|
|
def get_product(self, product_id):
|
|
if product_id:
|
|
product_qs = models.Product.objects.filter(old_id=product_id)
|
|
if product_qs.exists():
|
|
return product_qs.first()
|