"""Pydantic v2 request schemas — catalog domain.""" from decimal import Decimal from typing import Literal from uuid import UUID from pydantic import Field from app.schemas.common import APIModel MaterialStatus = Literal["active", "discontinued", "draft"] AttributeDataType = Literal["number", "integer", "string", "enum", "boolean", "date"] class UnitCreate(APIModel): code: str = Field(min_length=1, max_length=255) name_fa: str | None = None dimension: str | None = None si_factor: Decimal = Field(default=Decimal("1.0"), gt=0) is_base: bool = False class UnitUpdate(APIModel): code: str | None = Field(default=None, min_length=1, max_length=255) name_fa: str | None = None dimension: str | None = None si_factor: Decimal | None = Field(default=None, gt=0) is_base: bool | None = None class BrandCreate(APIModel): name: str = Field(min_length=1) country: str | None = None class BrandUpdate(APIModel): name: str | None = Field(default=None, min_length=1) country: str | None = None class MaterialCategoryCreate(APIModel): slug: str = Field(min_length=1) name: str = Field(min_length=1) description: str | None = None is_active: bool = True class MaterialCategoryUpdate(APIModel): slug: str | None = Field(default=None, min_length=1) name: str | None = Field(default=None, min_length=1) description: str | None = None is_active: bool | None = None class AttributeDefinitionCreate(APIModel): attribute_key: str = Field(min_length=1) label: str = Field(min_length=1) data_type: AttributeDataType unit_id: int | None = None enum_values: list | None = None class AttributeDefinitionUpdate(APIModel): label: str | None = Field(default=None, min_length=1) data_type: AttributeDataType | None = None unit_id: int | None = None enum_values: list | None = None class CategoryAttributeCreate(APIModel): attribute_definition_id: UUID is_required: bool = False is_filterable: bool = False conditional_rules: dict | None = None sort_order: int = 0 class CategoryAttributeUpdate(APIModel): is_required: bool | None = None is_filterable: bool | None = None conditional_rules: dict | None = None sort_order: int | None = None class MaterialAttributeIn(APIModel): """One EAV value. `value` is coerced against attribute_definitions.data_type.""" attribute_definition_id: UUID value: int | float | str | bool | None = None class MaterialCreate(APIModel): name: str = Field(min_length=1) topic: str | None = None # تاپیک جلوی برنامه (Persian) — legacy canonical_unit_id: int status: MaterialStatus = "active" brand_ids: list[UUID] = Field(default_factory=list) attributes: list[MaterialAttributeIn] = Field(default_factory=list) class MaterialUpdate(APIModel): name: str | None = Field(default=None, min_length=1) topic: str | None = None canonical_unit_id: int | None = None status: MaterialStatus | None = None class BrandMaterialCreate(APIModel): brand_id: UUID material_id: UUID catalog_code: str | None = None is_active: bool = True class BrandMaterialUpdate(APIModel): # brand_id / material_id are immutable (UNIQUE pair) — not accepted here. catalog_code: str | None = None is_active: bool | None = None class MaterialUnitCreate(APIModel): brand_material_id: UUID | None = None unit_id: int conversion_factor: Decimal = Field(gt=0) is_default: bool = False class MaterialUnitUpdate(APIModel): unit_id: int | None = None conversion_factor: Decimal | None = Field(default=None, gt=0) is_default: bool | None = None class MaterialAttributeValuesPut(APIModel): attributes: list[MaterialAttributeIn] = Field(default_factory=list) class CategoryReferenceUnitPut(APIModel): ref_unit: str = Field(min_length=1) class UnitConversionCreate(APIModel): category_id: UUID brand: str | None = None from_unit: str = Field(min_length=1) to_unit: str = Field(min_length=1) factor: Decimal = Field(gt=0) class UnitConversionUpdate(APIModel): brand: str | None = None from_unit: str | None = Field(default=None, min_length=1) to_unit: str | None = Field(default=None, min_length=1) factor: Decimal | None = Field(default=None, gt=0) class StandardConversionCreate(APIModel): from_unit: str = Field(min_length=1) to_unit: str = Field(min_length=1) factor: Decimal = Field(gt=0) class StandardConversionUpdate(APIModel): from_unit: str | None = Field(default=None, min_length=1) to_unit: str | None = Field(default=None, min_length=1) factor: Decimal | None = Field(default=None, gt=0)