231 lines
6.8 KiB
Python
231 lines
6.8 KiB
Python
"""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",
|
|
]
|