"""来源业务的人工分类资料。""" from decimal import Decimal, InvalidOperation from typing import Literal from pydantic import BaseModel, ConfigDict, Field, model_validator from app.core.response import PageQuery class SalesRelationQuery(PageQuery): shipment_page: int = Field(default=1, ge=1, le=10000) order_page: int = Field(default=1, ge=1, le=10000) class SourceDocumentsQuery(PageQuery): entity: str | None = Field(default=None, max_length=32) class SourcePriceConfirmIn(BaseModel): model_config = ConfigDict(extra="forbid") revision: str = Field(pattern=r"^[0-9a-f]{64}$") evidence: str = Field(min_length=1, max_length=500) @model_validator(mode="after") def validate_evidence(self): self.evidence = self.evidence.strip() if not self.evidence: raise ValueError("核对依据不能为空") return self class GuidanceConfirmIn(BaseModel): """从业务发货明细登记对应发货月份的单位指导成本。""" model_config = ConfigDict(extra="forbid") shipment_item_id: int = Field(ge=1) amount: str = Field(min_length=1, max_length=32) evidence: str = Field(min_length=1, max_length=500) @model_validator(mode="after") def validate_values(self): self.evidence = self.evidence.strip() if not self.evidence: raise ValueError("核对依据不能为空") try: value = Decimal(self.amount) except (InvalidOperation, TypeError, ValueError): raise ValueError("指导成本必须为有效数字") from None if not value.is_finite() or value < 0 or value.as_tuple().exponent < -4: raise ValueError("指导成本最多保留4位小数且不能为负数") return self class SourceProductCategory(BaseModel): product_id: int = Field(ge=1) category: Literal["municipal_water", "rail_transit"] class SourceMaterialsIn(BaseModel): model_config = ConfigDict(extra="forbid") customer_type: Literal["personal", "manager_personal", "enterprise"] | None = None products: list[SourceProductCategory] = Field(default_factory=list, max_length=200) @model_validator(mode="after") def unique_products(self): if len({p.product_id for p in self.products}) != len(self.products): raise ValueError("产品不能重复") if self.customer_type is None and not self.products: raise ValueError("请选择要补充的分类") return self class SalesRelationConfirmIn(BaseModel): model_config = ConfigDict(extra="forbid") item_id: int = Field(ge=1) shipment_document_id: int = Field(ge=1) order_document_id: int | None = Field(default=None, ge=1) disposition: Literal["ORDER", "INDEPENDENT"] item_revision: str = Field(pattern=r"^[0-9a-f]{64}$") shipment_revision: str = Field(pattern=r"^[0-9a-f]{64}$") order_revision: str | None = Field(default=None, pattern=r"^[0-9a-f]{64}$") expected_version: int = Field(default=0, ge=0) evidence: str = Field(min_length=1, max_length=500) @model_validator(mode="after") def validate_relation(self): self.evidence = self.evidence.strip() if not self.evidence: raise ValueError("确认依据不能为空") if self.disposition == "ORDER" and (self.order_document_id is None or self.order_revision is None): raise ValueError("请选择并核对订单明细") if self.disposition == "INDEPENDENT" and (self.order_document_id is not None or self.order_revision is not None): raise ValueError("独立发货不应指定订单明细") return self class SalesRelationReleaseIn(BaseModel): model_config = ConfigDict(extra="forbid") item_id: int = Field(ge=1) expected_version: int = Field(ge=1) evidence: str = Field(min_length=1, max_length=500) @model_validator(mode="after") def validate_evidence(self): self.evidence = self.evidence.strip() if not self.evidence: raise ValueError("撤销依据不能为空") return self