"""DUS/品种保护 —— Pydantic 校验/序列化模型(描述符模板 / 测试记录 / 观测)。""" from datetime import date, datetime from pydantic import BaseModel, ConfigDict, Field from app.core.base_schema import CommonSchema # ---------- 描述符模板 ---------- class DusDescriptorBaseSchema(BaseModel): model_config = ConfigDict(from_attributes=True) descriptor_no: str = Field(..., description="描述符编号(UPOV TG/53 特性号)") trait_id: int | None = Field(default=None, description="关联性状字典 id") trait_code: str | None = Field(default=None, description="性状编码(快照)") descriptor_name: str = Field(..., description="特性中文名") expression_type: str = Field(default="QN", description="表达类型(QN/PQ/QL)") method: str | None = Field(default=None, description="测试方法") example_varieties: str | None = Field(default=None, description="标准/示例品种") test_stage: str | None = Field(default=None, description="测试生育期") required: str = Field(default="1", description="是否必测(1/0)") remark: str | None = Field(default=None, description="备注") class DusDescriptorCreateSchema(DusDescriptorBaseSchema): pass class DusDescriptorUpdateSchema(DusDescriptorBaseSchema): descriptor_no: str | None = Field(default=None, description="描述符编号") descriptor_name: str | None = Field(default=None, description="特性中文名") expression_type: str | None = Field(default=None, description="表达类型(QN/PQ/QL)") required: str | None = Field(default=None, description="是否必测(1/0)") class DusDescriptorOutSchema(DusDescriptorBaseSchema): id: int uuid: str trait_name: str | None = None created_time: datetime | None = None updated_time: datetime | None = None created_by: CommonSchema | None = None updated_by: CommonSchema | None = None class DusDescriptorQueryParam(BaseModel): descriptor_no: str | None = Field(default=None, description="描述符编号", json_schema_extra={"q": "like"}) descriptor_name: str | None = Field(default=None, description="特性中文名", json_schema_extra={"q": "like"}) trait_code: str | None = Field(default=None, description="关联性状编码", json_schema_extra={"q": "like"}) expression_type: str | None = Field(default=None, description="表达类型") test_stage: str | None = Field(default=None, description="测试生育期") # ---------- 测试记录 ---------- class DusTestBaseSchema(BaseModel): model_config = ConfigDict(from_attributes=True) test_name: str = Field(..., description="测试名称") germplasm_id: int | None = Field(default=None, description="申请/候选品种") trial_study_id: int | None = Field(default=None, description="测试点") tester: str | None = Field(default=None, description="测试人") test_date: date | None = Field(default=None, description="测试日期") status: str = Field(default="planning", description="状态(planning/testing/completed/report)") conclusion: str = Field(default="pending", description="结论(pending/distinct/not_distinct)") report_path: str | None = Field(default=None, description="报告附件路径") remark: str | None = Field(default=None, description="备注") class DusTestCreateSchema(DusTestBaseSchema): pass class DusTestUpdateSchema(DusTestBaseSchema): test_name: str | None = Field(default=None, description="测试名称") status: str | None = Field(default=None, description="状态") conclusion: str | None = Field(default=None, description="结论") class DusTestOutSchema(DusTestBaseSchema): id: int uuid: str germplasm_name: str | None = None trial_study_name: str | None = None analysis_json: dict | None = None created_time: datetime | None = None updated_time: datetime | None = None created_by: CommonSchema | None = None updated_by: CommonSchema | None = None class DusDistinctnessIn(BaseModel): """特异性统计判定入参(§8.18)。""" reference_test_ids: list[int] | None = Field( default=None, description="显式参照测试 id 列表;为空则自动取同测试点其他非软删测试" ) alpha: float = Field( default=0.01, gt=0.0, lt=0.5, description="显著性水平(默认 1% 双侧,UPOV LSD 惯例)", ) class DusTestQueryParam(BaseModel): test_name: str | None = Field(default=None, description="测试名称", json_schema_extra={"q": "like"}) tester: str | None = Field(default=None, description="测试人", json_schema_extra={"q": "like"}) germplasm_id: int | None = Field(default=None, description="申请/候选品种") trial_study_id: int | None = Field(default=None, description="测试点") status: str | None = Field(default=None, description="状态") conclusion: str | None = Field(default=None, description="结论") # ---------- 观测 ---------- class DusObservationBaseSchema(BaseModel): model_config = ConfigDict(from_attributes=True) dus_test_id: int = Field(..., description="DUS 测试") dus_descriptor_id: int = Field(..., description="描述符") value_numeric: float | None = Field(default=None, description="数值表达值") value_text: str | None = Field(default=None, description="文本表达值") expression_note: str | None = Field(default=None, description="表达说明") remark: str | None = Field(default=None, description="备注") class DusObservationCreateSchema(DusObservationBaseSchema): pass class DusObservationUpdateSchema(DusObservationBaseSchema): dus_test_id: int | None = Field(default=None, description="DUS 测试") dus_descriptor_id: int | None = Field(default=None, description="描述符") class DusObservationOutSchema(DusObservationBaseSchema): id: int uuid: str descriptor_no: str | None = None descriptor_name: str | None = None created_time: datetime | None = None updated_time: datetime | None = None created_by: CommonSchema | None = None updated_by: CommonSchema | None = None class DusObservationQueryParam(BaseModel): dus_test_id: int | None = Field(default=None, description="DUS 测试") dus_descriptor_id: int | None = Field(default=None, description="描述符")