"""Procurement item and attachment serializers.""" from drf_spectacular.utils import extend_schema_field from rest_framework import serializers from communications import comments_helpers from procurement.models import ProcurementItem, ProcurementItemAttachment from .common import _validate_expected_delivery_dates class ProcurementItemAttachmentSerializer(serializers.ModelSerializer): uploaded_by_name = serializers.CharField( source="uploaded_by.get_full_name", read_only=True, ) download_url = serializers.SerializerMethodField() thumbnail_url = serializers.SerializerMethodField() class Meta: model = ProcurementItemAttachment fields = [ "id", "file_name", "file_size", "mime_type", "uploaded_by", "uploaded_by_name", "created_at", "download_url", "thumbnail_url", ] read_only_fields = fields def get_download_url(self, obj) -> str: return f"/api/v1/procurement/items/{obj.item_id}/attachments/{obj.id}/" def get_thumbnail_url(self, obj) -> str | None: from procurement.media import procurement_attachment_media_kind if not procurement_attachment_media_kind(obj): return None return ( f"/api/v1/procurement/items/{obj.item_id}/attachments/{obj.id}/thumbnail/" ) class ProcurementItemSerializer(serializers.ModelSerializer): """Сериализатор для позиций заявки.""" estimated_unit_price = serializers.DecimalField( max_digits=12, decimal_places=2, required=False, allow_null=True, ) ordered_quantity = serializers.IntegerField( required=False, allow_null=True, min_value=0, ) received_quantity = serializers.IntegerField( required=False, allow_null=True, min_value=0, ) expected_delivery_dates = serializers.ListField( child=serializers.CharField(allow_blank=False, trim_whitespace=True), required=False, allow_empty=True, ) initial_comment = serializers.CharField( write_only=True, required=False, allow_blank=True, ) total_price = serializers.DecimalField( max_digits=12, decimal_places=2, read_only=True ) execution_status_display = serializers.SerializerMethodField() comments_count = serializers.SerializerMethodField() attachments = ProcurementItemAttachmentSerializer(many=True, read_only=True) attachments_count = serializers.IntegerField( source="attachments.count", read_only=True, ) @extend_schema_field(serializers.IntegerField()) def get_comments_count(self, obj): annotated_count = getattr(obj, "comments_count", None) if annotated_count is not None: return annotated_count from communications.comments_helpers import get_comment_count return get_comment_count(obj) @extend_schema_field(serializers.CharField()) def get_execution_status_display(self, obj): return obj.execution_status_display class Meta: model = ProcurementItem fields = [ "id", "request", "name", "description", "quantity", "unit", "estimated_unit_price", "total_price", "ordered_quantity", "received_quantity", "supplier_info", "links", "expected_delivery_dates", "actual_unit_price", "execution_status", "execution_status_display", "defective_at", "executor_comment", "initial_comment", "comments_count", "attachments", "attachments_count", "equipment", "created_at", ] read_only_fields = [ "id", "created_at", "total_price", "execution_status_display", "defective_at", "comments_count", "attachments", "attachments_count", ] def validate_expected_delivery_dates(self, value): return _validate_expected_delivery_dates(value) def create(self, validated_data): initial_comment = validated_data.pop("initial_comment", "").strip() item = super().create(validated_data) request = self.context.get("request") author = getattr(request, "user", None) if initial_comment and author and author.is_authenticated: comments_helpers.create_comment( obj=item, author=author, content=initial_comment, ) return item class ProcurementItemCreateSerializer(serializers.ModelSerializer): """Сериализатор для создания позиций (без request).""" estimated_unit_price = serializers.DecimalField( max_digits=12, decimal_places=2, required=False, allow_null=True, ) ordered_quantity = serializers.IntegerField( required=False, allow_null=True, min_value=0, ) received_quantity = serializers.IntegerField( required=False, allow_null=True, min_value=0, ) expected_delivery_dates = serializers.ListField( child=serializers.CharField(allow_blank=False, trim_whitespace=True), required=False, allow_empty=True, ) initial_comment = serializers.CharField( write_only=True, required=False, allow_blank=True, ) class Meta: model = ProcurementItem fields = [ "id", "name", "description", "quantity", "unit", "estimated_unit_price", "ordered_quantity", "received_quantity", "supplier_info", "links", "expected_delivery_dates", "actual_unit_price", "execution_status", "executor_comment", "initial_comment", ] read_only_fields = ["id"] def validate_expected_delivery_dates(self, value): return _validate_expected_delivery_dates(value) class ProcurementItemEditSerializer(ProcurementItemCreateSerializer): """Сериализатор для редактирования позиций внутри заявки.""" id = serializers.IntegerField(required=False) class Meta: model = ProcurementItem fields = [ "id", "name", "description", "quantity", "unit", "estimated_unit_price", "supplier_info", "links", "initial_comment", ]