181 lines
6.3 KiB
Python
181 lines
6.3 KiB
Python
"""Equipment serializers."""
|
||
|
||
from drf_spectacular.utils import extend_schema_field
|
||
from rest_framework import serializers
|
||
|
||
from procurement.models import Equipment
|
||
from procurement.services import InventoryNumberGenerator
|
||
|
||
from ..equipment_policy import (
|
||
EquipmentCreationPolicy,
|
||
EquipmentPolicyValidationError,
|
||
validate_responsible_department,
|
||
)
|
||
|
||
|
||
class EquipmentListSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор для списка оборудования."""
|
||
|
||
category_name = serializers.CharField(source="category.name", read_only=True)
|
||
category_icon = serializers.CharField(
|
||
source="category.icon", read_only=True, default="bi-box-seam"
|
||
)
|
||
department_name = serializers.CharField(source="department.name", read_only=True)
|
||
responsible_name = serializers.CharField(
|
||
source="responsible_person.get_full_name", read_only=True
|
||
)
|
||
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
||
is_under_warranty = serializers.BooleanField(read_only=True)
|
||
comments_count = serializers.IntegerField(read_only=True, default=0)
|
||
|
||
class Meta:
|
||
model = Equipment
|
||
fields = [
|
||
"id",
|
||
"name",
|
||
"inventory_number",
|
||
"serial_number",
|
||
"category",
|
||
"category_name",
|
||
"category_icon",
|
||
"status",
|
||
"status_display",
|
||
"department",
|
||
"department_name",
|
||
"responsible_person",
|
||
"responsible_name",
|
||
"location",
|
||
"purchase_date",
|
||
"purchase_cost",
|
||
"notes",
|
||
"is_under_warranty",
|
||
"comments_count",
|
||
"created_at",
|
||
"updated_at",
|
||
]
|
||
read_only_fields = [
|
||
"id",
|
||
"inventory_number",
|
||
"category_name",
|
||
"category_icon",
|
||
"department_name",
|
||
"responsible_name",
|
||
"status_display",
|
||
"is_under_warranty",
|
||
"comments_count",
|
||
"created_at",
|
||
"updated_at",
|
||
]
|
||
|
||
def create(self, validated_data):
|
||
"""Автоматическая генерация инвентарного номера при создании."""
|
||
validated_data["inventory_number"] = InventoryNumberGenerator.generate()
|
||
return super().create(validated_data)
|
||
|
||
def validate(self, attrs):
|
||
"""Validate department access and responsible-person consistency."""
|
||
request = self.context.get("request")
|
||
user = request.user if request else None
|
||
|
||
try:
|
||
if self.instance is None:
|
||
responsible = attrs.get("responsible_person")
|
||
if responsible is not None and not responsible.is_active:
|
||
raise EquipmentPolicyValidationError(
|
||
{
|
||
"responsible_person": (
|
||
"Ответственным может быть только активный сотрудник."
|
||
)
|
||
}
|
||
)
|
||
return EquipmentCreationPolicy.resolve(user).validate_create(attrs)
|
||
|
||
department = attrs.get("department", self.instance.department)
|
||
responsible = attrs.get(
|
||
"responsible_person",
|
||
self.instance.responsible_person,
|
||
)
|
||
responsible_changed = (
|
||
"responsible_person" in attrs
|
||
and getattr(responsible, "id", None)
|
||
!= self.instance.responsible_person_id
|
||
)
|
||
department_changed = (
|
||
"department" in attrs and department.id != self.instance.department_id
|
||
)
|
||
if (
|
||
responsible_changed
|
||
and responsible is not None
|
||
and not responsible.is_active
|
||
):
|
||
raise EquipmentPolicyValidationError(
|
||
{
|
||
"responsible_person": (
|
||
"Ответственным может быть только активный сотрудник."
|
||
)
|
||
}
|
||
)
|
||
if (
|
||
responsible is not None
|
||
and responsible.is_active
|
||
and (responsible_changed or department_changed)
|
||
):
|
||
validate_responsible_department(
|
||
department=department,
|
||
responsible=responsible,
|
||
)
|
||
return attrs
|
||
except EquipmentPolicyValidationError as exc:
|
||
raise serializers.ValidationError(exc.errors) from exc
|
||
|
||
|
||
class EquipmentDetailSerializer(serializers.ModelSerializer):
|
||
"""Сериализатор для детальной информации об оборудовании."""
|
||
|
||
category_name = serializers.CharField(source="category.name", read_only=True)
|
||
department_name = serializers.CharField(source="department.name", read_only=True)
|
||
responsible_name = serializers.CharField(
|
||
source="responsible_person.get_full_name", read_only=True
|
||
)
|
||
status_display = serializers.CharField(source="get_status_display", read_only=True)
|
||
is_under_warranty = serializers.BooleanField(read_only=True)
|
||
maintenance_count = serializers.SerializerMethodField()
|
||
|
||
class Meta:
|
||
model = Equipment
|
||
fields = [
|
||
"id",
|
||
"name",
|
||
"inventory_number",
|
||
"serial_number",
|
||
"category",
|
||
"category_name",
|
||
"status",
|
||
"status_display",
|
||
"department",
|
||
"department_name",
|
||
"responsible_person",
|
||
"responsible_name",
|
||
"location",
|
||
"purchase_date",
|
||
"warranty_until",
|
||
"is_under_warranty",
|
||
"purchase_cost",
|
||
"notes",
|
||
"maintenance_count",
|
||
"created_at",
|
||
"updated_at",
|
||
]
|
||
read_only_fields = [
|
||
"id",
|
||
"created_at",
|
||
"updated_at",
|
||
"is_under_warranty",
|
||
"maintenance_count",
|
||
]
|
||
|
||
@extend_schema_field(serializers.IntegerField())
|
||
def get_maintenance_count(self, obj):
|
||
"""Количество записей обслуживания."""
|
||
return obj.maintenance_history.count()
|