117 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Shared validation and aggregation helpers for procurement serializers."""
import re
from datetime import date
from rest_framework import serializers
from procurement.constants import ProcurementItemExecutionStatus
from procurement.models import ProcurementSettings
PROBLEM_ITEM_STATUSES = {
ProcurementItemExecutionStatus.REJECTED,
ProcurementItemExecutionStatus.COMPLETED_WITH_ISSUE,
ProcurementItemExecutionStatus.EDITED,
ProcurementItemExecutionStatus.DEFECTIVE,
}
DATE_RE = re.compile(r"^\d{4}-\d{2}-\d{2}$")
UNIT_DISPLAY_LABELS = {
"шт": "штуки",
"компл": "комплекты",
"упак": "упаковки",
"короб": "короба",
"пачка": "пачки",
"кг": "килограммы",
"г": "граммы",
"л": "литры",
"мл": "миллилитры",
"м": "метры",
"кв. м": "кв. метры",
"куб. м": "куб. метры",
"рулон": "рулоны",
"пара": "пары",
"услуга": "услуги",
"час": "часы",
}
def _normalize_unit(value):
return re.sub(r"\s+", " ", str(value or "").strip()).lower()
def _unit_display_label(value):
unit = _normalize_unit(value)
if not unit:
return "единиц"
return UNIT_DISPLAY_LABELS.get(unit, unit)
def _validate_expected_delivery_dates(value):
if value in (None, ""):
return []
if not isinstance(value, list):
raise serializers.ValidationError("Ожидаемые даты должны быть списком.")
result = []
for raw in value:
item = str(raw or "").strip()
if not item:
continue
if not DATE_RE.fullmatch(item):
raise serializers.ValidationError(
"Каждая ожидаемая дата должна быть в формате YYYY-MM-DD."
)
try:
parsed = date.fromisoformat(item)
except ValueError as exc:
raise serializers.ValidationError(
"Каждая ожидаемая дата должна быть корректной календарной датой."
) from exc
result.append(parsed.isoformat())
return result
def _expected_delivery_date_values(item):
dates = []
for raw in item.expected_delivery_dates or []:
if not isinstance(raw, str) or not DATE_RE.fullmatch(raw):
continue
try:
dates.append(date.fromisoformat(raw))
except ValueError:
continue
return dates
def _validate_processing_department_available(processing_department):
if not processing_department:
return
settings = ProcurementSettings.get_solo()
available_departments = settings.available_processing_departments.all()
if (
available_departments.exists()
and not available_departments.filter(pk=processing_department.pk).exists()
):
raise serializers.ValidationError(
{
"processing_department": (
"Выберите отдел-исполнитель из доступных для закупок."
)
}
)
def _request_items(obj):
return list(obj.items.all())
def _effective_ordered_quantity(item):
return item.effective_ordered_quantity
def _effective_received_quantity(item):
return item.effective_received_quantity