class VehicleHistorySerializer(serializers.ModelSerializer, EnumSupportSerializerMixin): actor = serializers.SlugRelatedField(slug_field='username', read_only=True) current_state = EnumField(VehicleDefinitionStates, read_only=True) previous_state = EnumField(VehicleDefinitionStates, read_only=True) class Meta: model = VehicleChangeHistory fields = ('actor', 'current_state', 'previous_state', 'at')
def filter_enum(queryset, name, value): enum_name = camelize(name) enum_class = getattr(importlib.import_module('.models', __package__), enum_name) # Use case insensitive search (lenient=True, to_internal_value) to convert input string to enum value file_type_field = EnumField(enum_class, lenient=True, read_only=True, ints_as_names=True) enum_value = file_type_field.to_internal_value(value) queryset = queryset.filter(**{name: enum_value}) return queryset
class VehicleSaveSerializer( ModelSerializer, EnumSupportSerializerMixin ): model_year = SlugRelatedField( slug_field='name', queryset=ModelYear.objects.all() ) make = SlugRelatedField( slug_field='name', queryset=Make.objects.all() ) vehicle_class_code = SlugRelatedField( slug_field='vehicle_class_code', queryset=VehicleClass.objects.all() ) vehicle_fuel_type = SlugRelatedField( slug_field='vehicle_fuel_code', queryset=FuelType.objects.all() ) validation_status = EnumField( VehicleDefinitionStatuses, read_only=True ) class Meta: model = Vehicle fields = ( 'id', 'make', 'model_name', 'model_year', 'range', 'validation_status', 'vehicle_class_code', 'vehicle_fuel_type' ) read_only_fields = ('validation_status', 'id',)
class CreditTransferSaveSerializer(ModelSerializer): """ Serializer to create a transfer """ status = EnumField(CreditTransferStatuses) content = CreditTransferContentSaveSerializer(allow_null=True, many=True) def create(self, validated_data): request = self.context.get('request') content = request.data.get('content') credit_transfer = CreditTransfer.objects.create( credit_to=validated_data.get('credit_to'), debit_from=validated_data.get('debit_from'), status=validated_data.get('status'), create_user=request.user.username, update_user=request.user.username) if content: serializer = CreditTransferContentSaveSerializer( data=content, many=True, context={'credit_transfer': credit_transfer}) serializer.is_valid(raise_exception=True) serializer.save() serializer = CreditTransferSerializer(credit_transfer, read_only=True) return serializer.data class Meta: model = CreditTransfer fields = ('id', 'status', 'credit_to', 'debit_from', 'content')
class VehicleSerializer(serializers.ModelSerializer, EnumSupportSerializerMixin): make = VehicleMakeSerializer() model = VehicleModelSerializer() model_year = ModelYearSerializer() state = EnumField(VehicleDefinitionStates, read_only=True) vehicle_fuel_type = VehicleFuelTypeSerializer() changelog = VehicleHistorySerializer(read_only=True, many=True) actions = serializers.SerializerMethodField() def get_actions(self, instance): user = self.context['request'].user gov = self.context['request'].user.is_government actions = [] if (gov and instance.state is VehicleDefinitionStates.SUBMITTED): actions.append('VALIDATED') actions.append('REJECTED') if (not gov and instance.state in [ VehicleDefinitionStates.DRAFT, VehicleDefinitionStates.NEW ]): actions.append('SUBMITTED') return actions class Meta: model = Vehicle fields = ('id', 'make', 'model', 'state', 'vehicle_fuel_type', 'range', 'model_year', 'changelog', 'actions') read_only_fields = ('state', )
class ProfileSerializer(ModelSerializer): visibility = EnumField(Visibility, lenient=True, ints_as_names=True) class Meta: model = Profile fields = ( "guid", "handle", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "location", "name", "nsfw", "url", "visibility", ) read_only_fields = ( "guid", "handle", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "url", )
class VehicleStatusChangeSerializer(ModelSerializer): validation_status = EnumField(VehicleDefinitionStatuses) def validate_validation_status(self, value): request = self.context.get('request') if value == VehicleDefinitionStatuses.SUBMITTED and \ not request.user.has_role('Submit ZEV'): raise PermissionDenied( "You do not have the permission to submit this vehicle." ) if value == VehicleDefinitionStatuses.VALIDATED and \ not request.user.has_role('Validate ZEV'): raise PermissionDenied( "You do not have the permission to validate this vehicle." ) return value def update(self, instance, validated_data): change_status( self.context['request'].user, instance, validated_data.get('validation_status') ) return instance class Meta: model = Vehicle fields = ('validation_status',)
class ProfileSerializer(ModelSerializer): followers_count = SerializerMethodField() following_count = SerializerMethodField() has_pinned_content = SerializerMethodField() user_following = SerializerMethodField() visibility = EnumField(Visibility, lenient=True, ints_as_names=True) class Meta: model = Profile fields = ( "followers_count", "following_count", "guid", "handle", "has_pinned_content", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "location", "name", "nsfw", "url", "user_following", "visibility", ) read_only_fields = ( "followers_count", "following_count", "guid", "handle", "has_pinned_content", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "url", "user_following", ) def get_following_count(self, obj): return obj.following.count() def get_followers_count(self, obj): return Profile.objects.followers(obj).count() def get_has_pinned_content(self, obj): user = self.context.get("request").user return Content.objects.profile_pinned(obj, user).exists() def get_user_following(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.id in request.user.profile.following_ids)
class SendEmailSerializer(EnumSupportSerializerMixin, serializers.Serializer): type = EnumField(enum=EmailLogType, required=True) recipients = PrimaryKeyRelatedField(many=True, queryset=User.objects.all()) text = serializers.CharField() lease = InstanceDictPrimaryKeyRelatedField( instance_class=Lease, queryset=Lease.objects.all(), related_serializer=LeaseSuccinctSerializer, required=False)
class VehicleHistorySerializer( ModelSerializer, EnumSupportSerializerMixin ): create_user = UserSerializer(read_only=True) validation_status = EnumField(VehicleDefinitionStatuses, read_only=True) class Meta: model = VehicleChangeHistory fields = ('create_timestamp', 'create_user', 'validation_status')
class VehicleStatusChangeSerializer(ModelSerializer): validation_status = EnumField(VehicleDefinitionStatuses) def validate_validation_status(self, value): request = self.context.get('request') if value == VehicleDefinitionStatuses.SUBMITTED: if self.instance.validation_status not in [ VehicleDefinitionStatuses.DRAFT, VehicleDefinitionStatuses.CHANGES_REQUESTED ]: raise ValidationError( "Model cannot be submitted at this time.") if not request.user.has_perm('SUBMIT_ZEV'): raise PermissionDenied( "You do not have the permission to submit this vehicle.") if value in [ VehicleDefinitionStatuses.VALIDATED, VehicleDefinitionStatuses.REJECTED ]: if self.instance.validation_status is not \ VehicleDefinitionStatuses.SUBMITTED: raise ValidationError( "Model cannot be validated at this time.") if not request.user.has_perm('VALIDATE_ZEV'): raise PermissionDenied( "You do not have the permission to validate this model.") return value def update(self, instance, validated_data): request = self.context.get('request') status = validated_data.get('validation_status') change_status(self.context['request'].user, instance, status) if status == VehicleDefinitionStatuses.VALIDATED: instance.credit_class = CreditClass.objects.filter( credit_class=instance.get_credit_class()).first() instance.credit_value = instance.get_credit_value() instance.update_user = request.user.username instance.save() return instance class Meta: model = Vehicle fields = ( 'validation_status', 'create_user', 'update_user', )
class VehicleStateChangeSerializer(serializers.ModelSerializer): state = EnumField(VehicleDefinitionStates) def update(self, instance, validated_data): change_state(self.context['request'].user, instance, validated_data.get('state')) return instance class Meta: model = Vehicle fields = ('state', )
class ApplicationSerializer(serializers.ModelSerializer): application_uuid = UUIDField(source="external_uuid") application_type = EnumField(ApplicationType, source="type", write_only=True) additional_applicant = ApplicantSerializer(write_only=True, allow_null=True) project_id = UUIDField(write_only=True) ssn_suffix = CharField(write_only=True, min_length=5, max_length=5) apartments = ApplicationApartmentSerializer(write_only=True, many=True) class Meta: model = Application fields = [ "application_uuid", "application_type", "ssn_suffix", "has_children", "additional_applicant", "right_of_residence", "project_id", "apartments", ] extra_kwargs = { # We only support creating applications for now, # and only the application UUID will be returned # in the response. "has_children": { "write_only": True }, "right_of_residence": { "write_only": True }, "project_id": { "write_only": True }, } def validate_ssn_suffix(self, value): date_of_birth = self.context["request"].user.profile.date_of_birth validator = SSNSuffixValidator(date_of_birth) try: validator(value) except ValidationError as e: _logger.warning( "Invalid SSN suffix for the primary applicant was received: %s", e) return value def create(self, validated_data): validated_data["profile"] = self.context["request"].user.profile return create_application(validated_data)
class TimeElementSerializer(serializers.Serializer): name = serializers.CharField() description = serializers.CharField() start_time = serializers.TimeField() end_time = serializers.TimeField() end_time_on_next_day = serializers.BooleanField() resource_state = EnumField(enum=State) full_day = serializers.BooleanField() periods = serializers.SerializerMethodField() def get_periods(self, obj): # Return only period ids for now # TODO: what else we would like to see in the API about the periods return [period.id for period in obj.periods]
class CreditDecisionConsumerSerializer(serializers.Serializer): status = EnumField(enum=CreditDecisionStatus) official_name = serializers.CharField(max_length=255) claimant = ClaimantSerializer() reasons = CreditDecisionReasonConsumerSerializer(many=True) created_at = serializers.DateTimeField() class Meta: fields = [ "claimant", "status", "official_name", "reasons", ]
class RecordOfSaleSerializer( ModelSerializer, EnumSupportSerializerMixin ): validation_status = EnumField(RecordOfSaleStatuses, read_only=True) vin_validation_status = EnumField(VINStatuses, read_only=True) vehicle = VehicleMinSerializer(read_only=True) credits = SerializerMethodField() icbc_verification = SerializerMethodField() def get_icbc_verification(self, obj): icbc_data = IcbcRegistrationData.objects.filter(vin__iexact=obj.vin).first() if icbc_data: serializer = IcbcRegistrationDataSerializer(icbc_data) return serializer.data return None def get_credits(self, obj): return obj.vehicle.get_credit_value() class Meta: model = RecordOfSale fields = ('id', 'vin', 'reference_number', 'vehicle', 'sale_date', 'validation_status', 'vin_validation_status', 'credits', 'icbc_verification')
class InvoiceCreateSerializer(UpdateNestedMixin, EnumSupportSerializerMixin, FieldPermissionsSerializerMixin, serializers.ModelSerializer): id = serializers.ReadOnlyField() recipient = InstanceDictPrimaryKeyRelatedField( instance_class=Contact, queryset=Contact.objects.all(), related_serializer=ContactSerializer) rows = InvoiceRowCreateUpdateSerializer(many=True) payments = InvoicePaymentCreateUpdateSerializer(many=True, required=False, allow_null=True) # Make total_amount, billed_amount, and type not requided in serializer and set them in create() if needed total_amount = serializers.DecimalField(max_digits=10, decimal_places=2, required=False) billed_amount = serializers.DecimalField(max_digits=10, decimal_places=2, required=False) type = EnumField(enum=InvoiceType, required=False) def create(self, validated_data): validated_data['state'] = InvoiceState.OPEN if not validated_data.get('total_amount'): total_amount = Decimal(0) for row in validated_data.get('rows', []): total_amount += row.get('amount', Decimal(0)) validated_data['total_amount'] = total_amount if not validated_data.get('billed_amount'): billed_amount = Decimal(0) for row in validated_data.get('rows', []): billed_amount += row.get('amount', Decimal(0)) validated_data['billed_amount'] = billed_amount if not validated_data.get('type'): validated_data['type'] = InvoiceType.CHARGE return super().create(validated_data) class Meta: model = Invoice exclude = ('deleted', ) read_only_fields = ('number', 'generated', 'sent_to_sap_at', 'sap_id', 'state', 'adjusted_due_date', 'credit_invoices')
class VehicleHistorySerializer(ModelSerializer, EnumSupportSerializerMixin): create_user = SerializerMethodField() validation_status = EnumField(VehicleDefinitionStatuses, read_only=True) def get_create_user(self, obj): user_profile = UserProfile.objects.filter(username=obj.create_user) if user_profile.exists(): serializer = MemberSerializer(user_profile.first(), read_only=True) return serializer.data return obj.create_user class Meta: model = VehicleChangeHistory fields = ('create_timestamp', 'create_user', 'validation_status')
class LeaseCreateSerializer(LeaseUpdateSerializer): relate_to = serializers.PrimaryKeyRelatedField( required=False, allow_null=True, queryset=Lease.objects.all()) relation_type = EnumField(required=False, allow_null=True, enum=LeaseRelationType) def override_permission_check_field_name(self, field_name): if field_name in ('relate_to', 'relation_type'): return 'related_leases' return field_name class Meta: model = Lease fields = '__all__' read_only_fields = ('is_invoicing_enabled', 'is_rent_info_complete')
class CreditTransferSerializer(ModelSerializer, EnumSupportSerializerMixin, CreditTransferBaseSerializer): credit_to = OrganizationSerializer() credit_transfer_content = CreditTransferContentSerializer(many=True, read_only=True) debit_from = OrganizationSerializer() status = EnumField(CreditTransferStatuses, read_only=True) update_user = SerializerMethodField() class Meta: model = CreditTransfer fields = ( 'create_timestamp', 'credit_to', 'credit_transfer_content', 'debit_from', 'id', 'status', 'update_user', )
class VehicleSerializer( ModelSerializer, EnumSupportSerializerMixin ): make = VehicleMakeSerializer() model_year = ModelYearSerializer() validation_status = EnumField(VehicleDefinitionStatuses, read_only=True) vehicle_fuel_type = VehicleFuelTypeSerializer() history = VehicleHistorySerializer(read_only=True, many=True) actions = SerializerMethodField() vehicle_class_code = VehicleClassSerializer() def get_actions(self, instance): user = self.context['request'].user gov = self.context['request'].user.is_government actions = [] if (gov and instance.validation_status is VehicleDefinitionStatuses.SUBMITTED): actions.append('VALIDATED') actions.append('REJECTED') if (not gov and instance.validation_status in [ VehicleDefinitionStatuses.DRAFT, VehicleDefinitionStatuses.NEW ]): actions.append('SUBMITTED') return actions class Meta: model = Vehicle fields = ( 'id', 'actions', 'history', 'make', 'model_name', 'model_year', 'range', 'validation_status', 'vehicle_class_code', 'vehicle_fuel_type' ) read_only_fields = ('validation_status',)
class InvoiceCreateSerializer(UpdateNestedMixin, EnumSupportSerializerMixin, FieldPermissionsSerializerMixin, serializers.ModelSerializer): id = serializers.ReadOnlyField() recipient = InstanceDictPrimaryKeyRelatedField(instance_class=Contact, queryset=Contact.objects.all(), related_serializer=ContactSerializer, required=False) tenant = InstanceDictPrimaryKeyRelatedField(instance_class=Tenant, queryset=Tenant.objects.all(), related_serializer=TenantSerializer, required=False) rows = InvoiceRowCreateUpdateSerializer(many=True) payments = InvoicePaymentCreateUpdateSerializer(many=True, required=False, allow_null=True) # Make total_amount, billed_amount, and type not required in the serializer and set them in create() if needed total_amount = serializers.DecimalField(max_digits=10, decimal_places=2, required=False) billed_amount = serializers.DecimalField(max_digits=10, decimal_places=2, required=False) type = EnumField(enum=InvoiceType, required=False) def override_permission_check_field_name(self, field_name): if field_name == 'tenant': return 'recipient' return field_name def validate(self, attrs): if not bool(attrs.get('recipient')) ^ bool(attrs.get('tenant')): raise ValidationError(_('Either recipient or tenant is required.')) if attrs.get('tenant') and attrs.get('tenant') not in attrs.get('lease').tenants.all(): raise ValidationError(_('Tenant not found in lease')) return attrs def create(self, validated_data): validated_data['state'] = InvoiceState.OPEN if not validated_data.get('total_amount'): total_amount = Decimal(0) for row in validated_data.get('rows', []): total_amount += row.get('amount', Decimal(0)) validated_data['total_amount'] = total_amount if not validated_data.get('billed_amount'): billed_amount = Decimal(0) for row in validated_data.get('rows', []): billed_amount += row.get('amount', Decimal(0)) validated_data['billed_amount'] = billed_amount if not validated_data.get('type'): validated_data['type'] = InvoiceType.CHARGE if validated_data.get('tenant'): today = datetime.date.today() tenant = validated_data.pop('tenant') billing_tenantcontact = tenant.get_billing_tenantcontacts(today, today).first() if not billing_tenantcontact: raise ValidationError(_('Billing contact not found for tenant')) validated_data['recipient'] = billing_tenantcontact.contact for row in validated_data.get('rows', []): row['tenant'] = tenant invoice = super().create(validated_data) invoice.invoicing_date = timezone.now().date() invoice.outstanding_amount = validated_data['total_amount'] invoice.save() return invoice class Meta: model = Invoice exclude = ('deleted',) read_only_fields = ('number', 'generated', 'sent_to_sap_at', 'sap_id', 'state', 'adjusted_due_date', 'credit_invoices', 'interest_invoices')
class SalesSubmissionSaveSerializer(ModelSerializer): validation_status = EnumField(SalesSubmissionStatuses) sales_submission_comment = SalesSubmissionCommentSerializer( allow_null=True, required=False) def validate_validation_status(self, value): request = self.context.get('request') instance = self.instance instance.validate_validation_status(value, request) return value def update(self, instance, validated_data): request = self.context.get('request') records = request.data.get('records') sales_submission_comment = validated_data.pop( 'sales_submission_comment', None) if sales_submission_comment: SalesSubmissionComment.objects.create( create_user=request.user.username, sales_submission=instance, comment=sales_submission_comment.get('comment')) if records is not None: RecordOfSale.objects.filter(submission_id=instance.id).delete() for record_id in records: row = SalesSubmissionContent.objects.filter( id=record_id).first() if row and row.vehicle: RecordOfSale.objects.create( sale_date=get_date(row.xls_sale_date, row.xls_date_type, row.xls_date_mode), submission=instance, validation_status=RecordOfSaleStatuses.VALIDATED, vehicle=row.vehicle, vin=row.xls_vin, vin_validation_status=VINStatuses.MATCHED, ) validation_status = validated_data.get('validation_status') if validation_status: SalesSubmissionHistory.objects.create( submission=instance, validation_status=validation_status, update_user=request.user.username, create_user=request.user.username, ) instance.validation_status = validation_status instance.update_user = request.user.username instance.save() return instance class Meta: model = SalesSubmission fields = ('id', 'organization', 'submission_date', 'submission_sequence', 'submission_id', 'validation_status', 'sales_submission_comment')
class ContentSerializer(serializers.ModelSerializer): author = LimitedProfileSerializer(read_only=True) content_type = EnumField(ContentType, ints_as_names=True, read_only=True) include_following = BooleanField(default=False) recipients = RecipientsField() user_is_author = SerializerMethodField() user_has_shared = SerializerMethodField() tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name") through = SerializerMethodField() through_author = SerializerMethodField() visibility = EnumField(Visibility, lenient=True, ints_as_names=True, required=False) class Meta: model = Content fields = ( "author", "content_type", "edited", "federate", "uuid", "has_twitter_oembed", "humanized_timestamp", "id", "is_nsfw", "include_following", "local", "order", "parent", "pinned", "recipients", "remote_created", "rendered", "reply_count", "root_parent", "service_label", "share_of", "shares_count", "show_preview", "tags", "text", "through", "through_author", "timestamp", "url", "user_is_author", "user_has_shared", "visibility", ) read_only_fields = ( "author", "content_type" "edited", "uuid", "has_twitter_oembed", "humanized_timestamp", "id", "is_nsfw", "local", "remote_created", "rendered", "reply_count", "root_parent", "share_of", "shares_count", "tags", "through", "through_author", "timestamp", "url", "user_is_author", "user_has_shared", ) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.cache_through_authors() def cache_through_authors(self): """ If we have 'throughs', cache author information here for all of them. """ request = self.context.get("request") if not self.context.get("throughs") or not request: self.context["throughs_authors"] = {} return throughs_ids = self.context["throughs"] ids = {value for _key, value in throughs_ids.items()} through_to_id = {value: key for key, value in throughs_ids.items()} throughs = Content.objects.visible_for_user( request.user).select_related("author").filter(id__in=list(ids)) self.context["throughs_authors"] = { through_to_id.get(c.id, c.id): c.author for c in throughs } def get_through(self, obj): """Through is generally required only for serializing content for streams.""" throughs = self.context.get("throughs") if not throughs: return obj.id return throughs.get(obj.id, obj.id) def get_through_author(self, obj): throughs_authors = self.context.get("throughs_authors") if not throughs_authors: return {} through_author = throughs_authors.get(obj.id, obj.author) if through_author != obj.author: return LimitedProfileSerializer( instance=through_author, read_only=True, context={ "request": self.context.get("request") }, ).data return {} def get_user_is_author(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.author == request.user.profile) def get_user_has_shared(self, obj): request = self.context.get("request") if not request: return False return Content.has_shared(obj.id, request.user.profile.id) if hasattr( request.user, "profile") else False def validate_parent(self, value): # Validate parent cannot be changed if self.instance and value != self.instance.parent: raise serializers.ValidationError( "Parent cannot be changed for an existing Content instance.") # Validate user can see parent if not self.instance and value: request = self.context.get("request") if not value.visible_for_user(request.user): raise serializers.ValidationError("Parent not found") return value def to_representation(self, instance: Content) -> Dict[str, Any]: result = dict(super().to_representation(instance)) if not self.get_user_is_author(instance): result["recipients"] = "" return result def save(self, **kwargs: Dict): """ Set possible recipients after save. """ updating = self.instance is not None raw_recipients = self.validated_data.pop("recipients", "") parent = self.validated_data.get("parent") user = self.context.get("request").user # Get previous recipients, if old instance previous_recipients = [] if updating: if not self.instance.author_id: self.instance.author = user.profile if self.instance.limited_visibilities.count(): previous_recipients = self.instance.limited_visibilities.values_list( "id", flat=True) if parent is not None: self.instance.parent = parent # HAXX to ensure visibility is empty when going in to save self.instance.visibility = None content = super().save(**kwargs) if content.visibility != Visibility.LIMITED or content.content_type == ContentType.SHARE: return content if content.content_type == ContentType.CONTENT: # Collect new recipients recipients = Profile.objects.filter( Q(handle__in=raw_recipients) | Q(fid__in=raw_recipients)).visible_for_user(user) # Add following, if included if self.validated_data.get("include_following"): recipients = recipients | user.profile.following.all() recipients = recipients.distinct() elif content.content_type == ContentType.REPLY: recipients = content.root_parent.limited_visibilities.all() else: return content # If old instance, first remove the now not present to trigger federation retraction if previous_recipients: to_remove = set(previous_recipients).difference( set(recipients.values_list("id", flat=True))) for remove_id in to_remove: profile = Profile.objects.get(id=remove_id) content.limited_visibilities.remove(profile) # Clear, then set, since federation will be triggered by m2m changed signal content.limited_visibilities.clear() content.limited_visibilities.set(recipients) return content def validate(self, data): """ Validate visibility is not required for replies. If given, make sure it is the same as parent. If not given, use parent visibility. """ parent = data.get("parent") if parent: if data.get("visibility" ) and parent.visibility != data.get("visibility"): raise serializers.ValidationError( "Visibility was given but it doesn't match parent.") data["visibility"] = parent.visibility else: if not self.instance and not data.get("visibility"): raise serializers.ValidationError("Visibility is required") return data def validate_text(self, value): """Sanitize text if user is untrusted.""" user = self.context.get("request").user if user.trusted_editor: return value return safe_text_for_markdown(value) def validate_recipients(self, value: Set[str]) -> Set[str]: if self.initial_data.get( "visibility", Visibility.PUBLIC.value) != Visibility.LIMITED.value: return value if not value and not self.initial_data.get("include_following"): raise serializers.ValidationError( "Recipients cannot be empty if not including followed users.") user = self.context.get("request").user validation_errors = [] for recipient in value: if not validate_handle(recipient) and not re.match( r"https?://", recipient): validation_errors.append(recipient) if len(validation_errors) > 0: msg = _( "This recipient couldn't be found (please check the format).", "These recipients couldn't be found (please check the format).", len(validation_errors)) raise serializers.ValidationError({ "code": "recipients_not_found_error", "message": msg, "payload": validation_errors, }) recipient_profiles = Profile.objects.filter( Q(handle__in=value) | Q(fid__in=value)).visible_for_user(user) # TODO we should probably try to lookup missing ones over the network first before failing if recipient_profiles.distinct().count() != len(set(value)): raise serializers.ValidationError( "Not all recipients could be found.") return value
class ContentSerializer(ModelSerializer): author = LimitedProfileSerializer(read_only=True) content_type = EnumField(ContentType, ints_as_names=True, read_only=True) user_following_author = SerializerMethodField() user_is_author = SerializerMethodField() user_has_shared = SerializerMethodField() tags = SlugRelatedField(many=True, read_only=True, slug_field="name") through = SerializerMethodField() visibility = EnumField(Visibility, lenient=True, ints_as_names=True) class Meta: model = Content fields = ( "author", "content_type", "edited", "guid", "humanized_timestamp", "id", "is_nsfw", "local", "order", "parent", "pinned", "remote_created", "rendered", "reply_count", "service_label", "share_of", "shares_count", "tags", "text", "through", "timestamp", "url", "user_following_author", "user_is_author", "user_has_shared", "visibility", ) read_only_fields = ( "author", "content_type" "edited", "guid", "humanized_timestamp", "id", "is_nsfw", "local", "parent", "remote_created", "rendered", "reply_count", "share_of", "shares_count", "tags", "through", "timestamp", "url", "user_following_author", "user_is_author", "user_has_shared", ) def get_through(self, obj): """Through is generally required only for serializing content for streams.""" throughs = self.context.get("throughs") if not throughs: return obj.id return throughs.get(obj.id, obj.id) def get_user_following_author(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.author_id in request.user.profile.following_ids) def get_user_is_author(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.author == request.user.profile) def get_user_has_shared(self, obj): request = self.context.get("request") if not request: return False return Content.has_shared(obj.id, request.user.profile.id) if hasattr( request.user, "profile") else False
class TimeElementSerializer(serializers.Serializer): start_time = serializers.TimeField() end_time = serializers.TimeField() resource_state = EnumField(enum=State) override = serializers.BooleanField() full_day = serializers.BooleanField()
class InvoicesInPeriodReport(ReportBase): name = _("Invoces in period") description = _( "Show all the invoices that have due date between start and end date") slug = "invoices_in_period" input_fields = { "start_date": forms.DateField(label=_("Start date"), required=True), "end_date": forms.DateField(label=_("End date"), required=True), "lease_type": forms.ModelChoiceField( label=_("Laskutuslaji"), queryset=LeaseType.objects.all(), empty_label=None, required=False, ), "invoice_state": forms.ChoiceField(label=_("Invoice state"), required=False, choices=InvoiceState.choices()), } output_fields = { "number": { "label": _("Number") }, "lease_type": { "source": get_lease_type, "label": _("Lease type") }, "lease_id": { "source": get_lease_id, "label": _("Lease id") }, "state": { "label": _("State"), "serializer_field": EnumField(enum=InvoiceState), }, "due_date": { "label": _("Due date"), "format": "date" }, "total_amount": { "label": _("Total amount"), "format": "money", "width": 13 }, "billed_amount": { "label": _("Billed amount"), "format": "money", "width": 13 }, "outstanding_amount": { "label": _("Outstanding amount"), "format": "money", "width": 13, }, "recipient_name": { "source": get_recipient_name, "label": _("Recipient name"), "width": 50, }, "recipient_address": { "source": get_recipient_address, "label": _("Recipient address"), "width": 50, }, } def get_data(self, input_data): qs = (Invoice.objects.filter( due_date__gte=input_data["start_date"], due_date__lte=input_data["end_date"], ).select_related( "lease", "lease__identifier", "lease__identifier__type", "lease__identifier__district", "lease__identifier__municipality", "recipient", ).order_by("lease__identifier__type__identifier", "due_date")) if input_data["invoice_state"]: qs = qs.filter(state=input_data["invoice_state"]) if input_data["lease_type"]: qs = qs.filter(lease__identifier__type=input_data["lease_type"]) return qs def get_response(self, request): codename = "leasing.can_generate_report_{}".format(self.slug) if not request.user.has_perm(codename): raise PermissionDenied() report_data = self.get_data(self.get_input_data(request)) serialized_report_data = self.serialize_data(report_data) if request.accepted_renderer.format != "xlsx": return Response(serialized_report_data) # Add totals row to xlsx output invoice_count = len(serialized_report_data) totals_row = ExcelRow() totals_row.cells.append(ExcelCell(column=0, value=str(_("Total")))) totals_row.cells.append( SumCell(column=5, target_ranges=[(0, 5, invoice_count - 1, 5)])) totals_row.cells.append( SumCell(column=6, target_ranges=[(0, 6, invoice_count - 1, 6)])) totals_row.cells.append( SumCell(column=7, target_ranges=[(0, 7, invoice_count - 1, 7)])) serialized_report_data.append(totals_row) return Response(serialized_report_data)
class ProfileSerializer(ModelSerializer): followed_tags = SerializerMethodField() followers_count = SerializerMethodField() following_count = SerializerMethodField() has_pinned_content = SerializerMethodField() user_following = SerializerMethodField() visibility = EnumField(Visibility, lenient=True, ints_as_names=True) class Meta: model = Profile fields = ( "fid", "followed_tags", "followers_count", "following_count", "uuid", "handle", "has_pinned_content", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "location", "name", "nsfw", "url", "user_following", "visibility", ) read_only_fields = ( "fid", "followed_tags", "followers_count", "following_count", "uuid", "handle", "has_pinned_content", "home_url", "id", "image_url_large", "image_url_medium", "image_url_small", "is_local", "url", "user_following", ) def get_followed_tags(self, obj: Profile) -> List: """ Return list of followed tags if owned by logged in user. """ user = self.context.get("request").user if (hasattr(user, "profile") and user.profile.id == obj.id) or user.is_staff: return list(obj.followed_tags.values_list('name', flat=True)) return [] def get_following_count(self, obj): return obj.following.count() def get_followers_count(self, obj): return Profile.objects.followers(obj).count() def get_has_pinned_content(self, obj): user = self.context.get("request").user return Content.objects.profile_pinned(obj, user).exists() def get_user_following(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.id in request.user.profile.following_ids)
class DummySerializer(Serializer): resource_state = EnumField(enum=State)
class ContentSerializer(serializers.ModelSerializer): author = LimitedProfileSerializer(read_only=True) content_type = EnumField(ContentType, ints_as_names=True, read_only=True) user_following_author = SerializerMethodField() user_is_author = SerializerMethodField() user_has_shared = SerializerMethodField() tags = serializers.SlugRelatedField(many=True, read_only=True, slug_field="name") through = SerializerMethodField() visibility = EnumField(Visibility, lenient=True, ints_as_names=True, required=False) class Meta: model = Content fields = ( "author", "content_type", "edited", "uuid", "has_twitter_oembed", "humanized_timestamp", "id", "is_nsfw", "local", "order", "parent", "pinned", "remote_created", "rendered", "reply_count", "service_label", "share_of", "shares_count", "tags", "text", "through", "timestamp", "url", "user_following_author", "user_is_author", "user_has_shared", "visibility", ) read_only_fields = ( "author", "content_type" "edited", "uuid", "has_twitter_oembed", "humanized_timestamp", "id", "is_nsfw", "local", "remote_created", "rendered", "reply_count", "share_of", "shares_count", "tags", "through", "timestamp", "url", "user_following_author", "user_is_author", "user_has_shared", ) def get_through(self, obj): """Through is generally required only for serializing content for streams.""" throughs = self.context.get("throughs") if not throughs: return obj.id return throughs.get(obj.id, obj.id) def get_user_following_author(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.author_id in request.user.profile.following_ids) def get_user_is_author(self, obj): request = self.context.get("request") if not request: return False return bool(request.user.is_authenticated and obj.author == request.user.profile) def get_user_has_shared(self, obj): request = self.context.get("request") if not request: return False return Content.has_shared(obj.id, request.user.profile.id) if hasattr(request.user, "profile") else False def validate(self, data): """ Validate visibility is not required for replies. If given, make sure it is the same as parent. If not given, use parent visibility. """ parent = data.get("parent") if parent: if data.get("visibility") and parent.visibility != data.get("visibility"): raise serializers.ValidationError("Visibility was given but it doesn't match parent.") data["visibility"] = parent.visibility else: if not self.instance and not data.get("visibility"): raise serializers.ValidationError("Visibility is required") return data def validate_parent(self, value): # Validate parent cannot be changed if self.instance and value != self.instance.parent: raise serializers.ValidationError("Parent cannot be changed for an existing Content instance.") # Validate user can see parent if not self.instance and value: request = self.context.get("request") if not value.visible_for_user(request.user): raise serializers.ValidationError("Parent not found") return value def validate_visibility(self, value): """ Don't allow creating Limited visibility as of now. """ if value == Visibility.LIMITED and not self.instance: raise serializers.ValidationError("Limited content creation not yet supported via the API.") return value