"""通用观测 —— Pydantic 校验/序列化模型。""" from datetime import date, datetime from pydantic import BaseModel, ConfigDict, Field from app.core.base_schema import CommonSchema class ObservationBaseSchema(BaseModel): model_config = ConfigDict(from_attributes=True) tree_id: int | None = Field(default=None, description="单株(可空)") plot_id: int | None = Field(default=None, description="小区(可空)") germplasm_id: int | None = Field(default=None, description="种质资源(可空,描述性观测)") trait_id: int | None = Field(default=None, description="性状(可空,EAV)") obs_date: date | None = Field(default=None, description="观测日期") obs_year: int | None = Field(default=None, description="观测年份") obs_value: str | None = Field(default=None, description="观测值(text多态,按obs_type解释)") obs_type: str = Field(..., description="观测类型(numeric/text/date)") trial_study_id: int | None = Field(default=None, description="试验(可空)") operator_id: int | None = Field(default=None, description="观测人") remark: str | None = Field(default=None, description="备注") class ObservationCreateSchema(ObservationBaseSchema): pass class ObservationUpdateSchema(ObservationBaseSchema): tree_id: int | None = Field(default=None, description="单株(可空)") plot_id: int | None = Field(default=None, description="小区(可空)") germplasm_id: int | None = Field(default=None, description="种质资源(可空,描述性观测)") trait_id: int | None = Field(default=None, description="性状(可空,EAV)") obs_date: date | None = Field(default=None, description="观测日期") obs_year: int | None = Field(default=None, description="观测年份") obs_value: str | None = Field(default=None, description="观测值(text多态,按obs_type解释)") obs_type: str | None = Field(default=None, description="观测类型(numeric/text/date)") trial_study_id: int | None = Field(default=None, description="试验(可空)") operator_id: int | None = Field(default=None, description="观测人") remark: str | None = Field(default=None, description="备注") class ObservationOutSchema(ObservationBaseSchema): id: int uuid: str tree_id: int | None = None plot_id: int | None = None germplasm_id: int | None = None trait_id: int | None = None obs_date: date | None = None obs_year: int | None = None obs_value: str | None = None obs_type: str | None = None trial_study_id: int | None = None operator_id: int | None = None remark: str | None = None status: int | None = None tree_no: str | None = None # 由 Service 层联表填充 plot_label: str | None = None # 由 Service 层联表填充 ({site_name}-{plot_code}) germplasm_name: str | None = None # 由 Service 层联表填充 trait_name: str | None = None # 由 Service 层联表填充 trial_study_name: str | None = None # 由 Service 层联表填充 operator_name: str | None = None # 由 Service 层联表填充 created_time: datetime | None = None updated_time: datetime | None = None created_by: CommonSchema | None = None updated_by: CommonSchema | None = None class ObservationQueryParam(BaseModel): obs_type: str | None = Field(default=None, description="观测类型", json_schema_extra={"q": "eq"}) obs_year: int | None = Field(default=None, description="观测年份", json_schema_extra={"q": "eq"}) trait_id: int | None = Field(default=None, description="性状", json_schema_extra={"q": "eq"}) tree_id: int | None = Field(default=None, description="单株", json_schema_extra={"q": "eq"}) plot_id: int | None = Field(default=None, description="小区", json_schema_extra={"q": "eq"}) germplasm_id: int | None = Field(default=None, description="种质资源", json_schema_extra={"q": "eq"}) trial_study_id: int | None = Field(default=None, description="试验/站点", json_schema_extra={"q": "eq"})