from generic_relations.relations import GenericRelatedField from rest_framework import serializers from rest_framework.serializers import ModelSerializer, ImageField, FileField, PrimaryKeyRelatedField, ListSerializer from common.serializers import LocationSerializer, ContentTypeSerializer from specializations.serializers import SpecializationSerializer from users.models import User, Team from users.serializers import UserSerializer, TeamSerializer from .models import Project, Realty, BuildingClassfication, ConstructionType, Order, Stage, Portfolio, PortfolioPhoto, \ Answer, AnswerFile class AnswerFileSerializer(ModelSerializer): file = FileField() class Meta: model = AnswerFile fields = ( 'file', 'id', 'name', # 'answer', ) class PortfolioPhotoSerializer(ModelSerializer): img = ImageField() portfolio_id = PrimaryKeyRelatedField(read_only=True, source='portfolio') class Meta: model = PortfolioPhoto fields = ( 'id', 'img', 'portfolio_id', ) class BuildingClassficationSerializer(ModelSerializer): class Meta: model = BuildingClassfication fields = ( 'id', 'name', ) class NestedBuildingClassificationSerializerOnlyId(ModelSerializer): class Meta: model = BuildingClassfication fields = ( 'id', ) class BuildingClassificationSerializeFlat(ModelSerializer): children = NestedBuildingClassificationSerializerOnlyId(many=True) parent = NestedBuildingClassificationSerializerOnlyId() class Meta: model = BuildingClassfication fields = ( 'id', 'name', 'children', 'parent') class ConstructionTypeSerializer(ModelSerializer): class Meta: model = ConstructionType fields = ( 'id', 'name', ) class RealtySerializer(ModelSerializer): building_classification = BuildingClassficationSerializer() construction_type = ConstructionTypeSerializer() location = LocationSerializer() user = UserSerializer() class Meta: model = Realty fields = ( 'id', 'name', 'building_classification', 'construction_type', 'location', 'user', ) class StageListSerializer(ListSerializer): def update(self, instance, validated_data): # Maps for id->instance and id->data item. # print("instance = ", instance) # print("validated_data = ", validated_data) obj_mapping = {obj.id: obj for obj in instance} data_mapping = {item['id']: item for item in validated_data} # Perform creations and updates. # print("obj_mapping = ", obj_mapping) # print("data_mapping = ", data_mapping) ret = [] for obj_id, data in data_mapping.items(): obj = obj_mapping.get(obj_id, None) if obj is None: ret.append(self.child.create(data)) else: ret.append(self.child.update(obj, data)) # Perform deletions. for obj_id, obj in obj_mapping.items(): if obj_id not in data_mapping: obj.delete() return ret class StageSerializer(ModelSerializer): term = serializers.DateField(format="%d.%m.%Y", input_formats=['%d.%m.%Y', ]) def validate(self, data): if 'pos' in data and data['pos'] > 1: pos = data['pos'] - 1 stage_last = Stage.objects.filter(order=data['order'], pos=pos) if stage_last: stage_last = stage_last[0] if stage_last.term > data['term']: raise serializers.ValidationError({'term': 'Дата не должна быть меньше даты предыдущео этапа'}) return data class Meta: model = Stage fields = ( 'id', 'cost', 'cost_type', 'term', 'term_type', 'name', 'order', 'result', 'pos', 'status', 'is_paid', 'close_contractor', 'close_customer', ) list_serializer_class = StageListSerializer class OrderSerializer_(ModelSerializer): contractor = UserSerializer() stages = StageSerializer(many=True) team = TeamSerializer() project_id = PrimaryKeyRelatedField(read_only=True, source='project') class Meta: model = Order fields = ( 'created', 'id', 'secure', 'status', 'contractor', 'project_id', 'stages', 'team', ) class AnswerSerializer_(ModelSerializer): project_id = PrimaryKeyRelatedField(read_only=True, source='project') portfolio_ids = PrimaryKeyRelatedField(read_only=True, source='portfolios', many=True) content_type = ContentTypeSerializer() files = AnswerFileSerializer(many=True) author = GenericRelatedField({ User: UserSerializer(), Team: TeamSerializer() }) class Meta: model = Answer fields = ( 'budget', 'created', 'currency', 'id', 'is_archive', 'object_id', 'portfolio_ids', 'project_id', 'rejected', 'secure_deal_only', 'term', 'term_type', 'author', # Generic related field 'content_type', 'files', ) class ProjectSerializer(ModelSerializer): answers = AnswerSerializer_(many=True) customer = UserSerializer() order = OrderSerializer_() # TODO: Can't serialize a reverse/reciprocal relation realty = RealtySerializer() specialization = SpecializationSerializer() class Meta: model = Project fields = ( 'answers', 'budget', 'budget_by_agreement', 'created', 'cro', 'currency', 'customer', 'deal_type', 'id', 'name', 'order', 'price_and_term_required', 'realty', 'specialization', 'state', 'term', 'term_type', 'text', 'work_type', ) class OrderSerializer(ModelSerializer): stages = StageSerializer(many=True, read_only=True) project = ProjectSerializer(read_only=True) has_user_review = serializers.SerializerMethodField(read_only=True) contractor_name = serializers.SerializerMethodField(read_only=True) class Meta: model = Order fields = ( 'id', 'contractor', 'team', 'created', 'project', 'secure', 'status', 'has_user_review', 'stages', 'project', 'contractor_name', ) def get_contractor_name(self, obj): if obj.contractor: return obj.contractor.get_full_name() or obj.contractor.username elif obj.team: return obj.team.owner.get_full_name() or obj.team.owner.username else: return 'Исполнитель не определен' def get_has_user_review(self, obj): "Имеет отзывы" curr_user = self.context['request'].user if curr_user.is_customer(): return curr_user.customer_reviews.filter(project=obj.project).exists() elif curr_user.is_contractor(): if obj.team is None and obj.contractor: return curr_user.contractor_reviews.filter(project=obj.project).exists() elif curr_user.team: return curr_user.team.team_reviews.filter(project=obj.project).exists() else: return False class PortfolioSerializer(ModelSerializer): # answers = AnswerSerializer(many=True) building_classification = BuildingClassficationSerializer() construction_type = ConstructionTypeSerializer() location = LocationSerializer() photos = PortfolioPhotoSerializer(many=True) specialization = SpecializationSerializer() user = UserSerializer() class Meta: model = Portfolio fields = ( # 'answers', 'building_classification', 'construction_type', 'location', 'photos', 'specialization', 'user', 'budget', 'currency', 'description', 'id', 'name', 'term', 'term_type', 'worksell', ) class AnswerSerializer(ModelSerializer): content_type = ContentTypeSerializer() files = AnswerFileSerializer(many=True) portfolios = PortfolioSerializer(many=True) project = ProjectSerializer() author = GenericRelatedField({ User: UserSerializer(), Team: TeamSerializer() }) class Meta: model = Answer fields = ( 'budget', 'created', 'currency', 'id', 'is_archive', 'object_id', 'rejected', 'secure_deal_only', 'term', 'term_type', 'author', # Generic related field 'content_type', 'files', 'portfolios', 'project', # 'candidates', )