fix:sample/plate 之前的开发

This commit is contained in:
彭帅
2026-05-28 11:56:17 +08:00
parent fc36bc83e3
commit 8b65de36b8
367 changed files with 57752 additions and 947 deletions

View File

@@ -0,0 +1,609 @@
# Germplasm / Seed 模块专业数据录入需求文档 V2
## 1. 文档目的
本文档用于指导 Germplasm / Seed 模块的前端页面、后端接口、字段校验、数据导入、测试验收设计。本文档不再只描述数据库表关系,而是从真实育种业务出发,解释每个字段的业务意义、录入方式、控件建议、校验规则和上下游影响。
## 2. 模块定位
Germplasm / Seed 模块描述育种材料的生命周期:
```text
材料身份 -> 材料属性 -> 杂交计划/实际杂交 -> 亲本 -> 系谱 -> 种子批次 -> 库存流转 -> 被 study / observation_unit 使用
```
核心概念如下:
| 概念 | 业务含义 | 主要表 |
| ---------------------------- | --------------------------------------------------------- | ------------------------------------------------------------ |
| Germplasm 材料身份 | 一个品种、品系、后代材料、种质资源的身份信息 | `germplasm` |
| Germplasm Attribute 材料属性 | 材料自身稳定特征,如抗性、熟期、籽粒硬度、基因/QTL 标记等 | `germplasm_attribute_definition``germplasm_attribute_value` |
| Cross 杂交动作 | 一次计划杂交或实际杂交,包含亲本、状态、项目归属 | `crossing_project``cross_entity``cross_parent` |
| Pedigree 系谱 | 材料之间的亲子、同胞、后代关系 | `pedigree_node``pedigree_edge` |
| SeedLot 种子批次 | 某个材料或杂交组合对应的一批实物种子,有数量、单位、库位 | `seed_lot``seed_lot_content_mixture` |
| Transaction 库存流转 | 入库、出库、转移、分装、合并、消耗等动作流水 | `seed_lot_transaction` |
## 3. 推荐业务流程
```text
1. 维护育种方法 breeding_method
2. 维护材料属性定义 germplasm_attribute_definition
3. 创建材料 germplasm
4. 给材料补充属性值 germplasm_attribute_value
5. 如涉及杂交,创建 crossing_project
6. 创建计划杂交 cross_entity(planned=true)
7. 给计划杂交录入亲本 cross_parent
8. 实际完成杂交后,创建实际杂交 cross_entity(planned=false, planned_cross_id=计划杂交)
9. 如产生后代材料,创建新的 germplasm并补充 pedigree_node / pedigree_edge
10. 如产生实物种子,创建 seed_lot
11. 在 seed_lot_content_mixture 中描述批次组成
12. 后续库存变化通过 seed_lot_transaction 记录
13. seed_lot / germplasm / cross_entity 后续可作为 observation_unit 的材料来源
```
## 4. 页面总体设计
### 4.1 Germplasm 材料详情页
```text
Germplasm 详情页
├─ 基本信息名称、默认显示名、PUI、accession、作物、育种方法
├─ 分类信息genus、species、subtaxa、country_of_origin_code
├─ 来源信息acquisition_date、seed_source、seed_source_description、collection
├─ 属性值germplasm_attribute_value
├─ 系谱pedigree_node / pedigree_edge 树图
├─ 作为亲本cross_parent
├─ 种子批次seed_lot_content_mixture -> seed_lot
└─ 下游使用observation_unit、reference_set、sample 追踪
```
### 4.2 SeedLot 库存详情页
```text
SeedLot 详情页
├─ 当前库存amount、units、location、storage_location
├─ 批次组成germplasm / cross / mixture_percentage
├─ 出入库操作:入库、出库、转移、分装、合并、消耗
├─ 流转流水seed_lot_transaction
└─ 下游使用:哪些 study / observation_unit 使用了该批种子
```
### 4.3 CrossingProject 杂交项目工作台
```text
CrossingProject 工作台
├─ 项目信息name、program、description
├─ 计划杂交cross_entity(planned=true)
├─ 实际杂交cross_entity(planned=false)
├─ 亲本cross_parent
├─ 后代材料germplasm / pedigree_node
└─ 产生种子批次seed_lot
```
---
# 5. 字段级专业录入需求
## 5.1 breeding_method 育种方法
### 业务说明
`breeding_method` 是育种方法字典,用来说明某个 germplasm 是通过什么方式形成的,例如杂交选育、回交、自交系选育、诱变、转基因、克隆选择等。它不是一次具体杂交动作,而是材料来源方法的分类。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------- | -------------------------------------------- | -------------------------------- | --------- | -------------------------------- |
| `id` | 育种方法主键,系统内部唯一标识 | 新增时系统生成;导入时可允许指定 | 隐藏/只读 | 必填、唯一;编辑时不允许修改 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许前端手填 |
| `abbreviation` | 方法缩写,如 MB、BC、DH | 用户录入 | 文本框 | 可选;建议同一用户下唯一 |
| `description` | 方法解释,如“回交用于恢复目标基因” | 用户录入 | 多行文本 | 可选,限制长度 |
| `name` | 方法名称,如 Male Backcross、Doubled Haploid | 用户录入 | 文本框 | 必填;建议唯一;作为下拉展示名称 |
### 页面与交互
- 列表页展示:方法名称、缩写、描述、使用材料数量。
- 新增页为简单字典表单。
- 删除前检查是否被 `germplasm.breeding_method_id` 引用;已引用时不允许物理删除,只允许停用。
---
## 5.2 germplasm 种质 / 材料身份
### 业务说明
`germplasm` 是材料身份证,描述一个品种、品系、亲本、后代材料、遗传资源或研究材料“是谁”。它不表示库存数量,库存数量由 `seed_lot` 表达。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------------------------- | ------------------------------------------------------------ | -------------------------------------- | ----------------- | --------------------------------------------------------- |
| `id` | 种质主键,系统内部唯一标识 | 系统生成;导入可指定 | 隐藏/只读 | 必填、唯一;编辑不可随意修改 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `accession_number` | 材料在种质库/机构内的 accession 编号,如 PI 113869 | 用户录入或导入 | 文本框 | 可选;建议同一 crop / institution 下唯一 |
| `acquisition_date` | 材料进入本系统或本机构的获取日期 | 用户录入 | 日期选择器 | 可选;不得晚于当前日期太多,导入时允许缺月/缺日需统一规则 |
| `acquisition_source_code` | 获取来源编码,如采集、引进、交换、繁殖等 | 用户选择 | 下拉框 | 可选;值来自 BrAPI/MCPD 枚举或系统字典 |
| `biological_status_of_accession_code` | 材料生物状态,如野生、地方品种、育种材料、改良品种、突变体等 | 用户选择 | 下拉框 | 可选;使用受控枚举,不建议自由输入 |
| `collection` | 材料所属集合、群体、panel 或 collection | 用户录入/选择 | 文本框/选择器 | 可选;可用于分组筛选 |
| `country_of_origin_code` | 原产国或育成/选育国家代码 | 用户选择 | 国家代码选择器 | 可选;建议使用 ISO 3166-1 三字母代码 |
| `default_display_name` | 系统默认展示名,给下拉框、表格、详情标题使用 | 用户录入,可由 germplasm_name 自动带出 | 文本框 | 与 `germplasm_name` 至少填一个;建议必填 |
| `documentationurl` | 材料说明文档、外部数据库页面或 DOI 链接 | 用户录入 | URL 输入框 | 可选;校验 URL 格式 |
| `genus` | 属名,如 Oryza、Triticum | 用户录入/字典选择 | 文本框/物种选择器 | 可选;建议首字母大写 |
| `germplasm_name` | 材料名称,可以是品种名、品系名、后代编号 | 用户录入 | 文本框 | 与 `default_display_name` 至少填一个;不强制全局唯一 |
| `germplasmpui` | 永久唯一标识,通常是 DOI、URI 或全局唯一编码 | 用户录入/外部导入 | 文本框/URL 输入框 | 可选;若填写必须唯一;建议用于跨系统交换 |
| `germplasm_preprocessing` | 材料用于试验前的统一处理说明,如消毒、催芽、低温处理 | 用户录入 | 文本框/多行文本 | 可选 |
| `mls_status` | 多边系统 MLS 状态,涉及植物遗传资源交换协议 | 用户选择 | 下拉框 | 可选;普通业务可隐藏到高级信息 |
| `seed_source` | 材料来源标识,如来源机构+accession或亲本组合描述 | 用户录入 | 文本框 | 可选;注意它不是库存批次,不等于 seed_lot |
| `seed_source_description` | 材料来源详细说明 | 用户录入 | 多行文本 | 可选 |
| `species` | 种名,如 sativa、aestivum | 用户录入/物种字典 | 文本框 | 可选;建议小写 |
| `species_authority` | 种名命名权威,如 L. | 用户录入 | 文本框 | 可选 |
| `subtaxa` | 亚种、变种、品种群、line 等更细分类 | 用户录入 | 文本框 | 可选 |
| `subtaxa_authority` | 亚种/变种命名权威 | 用户录入 | 文本框 | 可选 |
| `breeding_method_id` | 该材料形成所使用的育种方法 | 从 breeding_method 选择 | 搜索选择器 | 可选;必须引用存在的 breeding_method |
| `crop_id` | 所属作物 | 从 crop 选择 | 作物选择器 | 必填;后续 trial/study/attribute 应尽量同 crop |
### 录入建议
- 新建材料时,第一屏只放核心字段:`crop_id``germplasm_name``default_display_name``germplasmpui``accession_number``breeding_method_id`
- 分类与来源信息放在“高级信息”或“来源信息”分组。
- `germplasmpui``accession_number``germplasm_name` 三者不要混为一谈:
- `germplasm_name` 是人看的名字;
- `accession_number` 是机构内编号;
- `germplasmpui` 是跨系统长期唯一标识。
### 验收标准
1. 新增 germplasm 时,必须选择 crop。
2. `germplasm_name``default_display_name` 至少填写一个。
3. 下拉选择材料时展示 `default_display_name`,辅助展示 accession number / PUI。
4. 如果 germplasm 已被 seed lot、cross parent、observation unit 引用,不允许物理删除。
---
## 5.3 germplasm_attribute_definition 属性定义
### 业务说明
属性定义描述“材料可以有哪些稳定属性”。这些属性通常不是环境依赖的田间观测值,而是材料自身特征,例如籽粒颜色、抗病基因、硬度、熟期类型、特定 QTL、分子标记结果等。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ---------------------- | ------------------------------------------------------------ | ---------------------------- | ----------------- | ------------------------------------- |
| `id` | 属性定义主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `default_value` | 属性默认值 | 用户录入 | 动态输入框 | 可选;按 datatype / scale 校验 |
| `documentationurl` | 属性说明文档链接 | 用户录入 | URL 输入框 | 可选;校验 URL |
| `growth_stage` | 属性适用生长阶段,如 flowering | 用户录入/选择 | 下拉框/文本框 | 可选 |
| `institution` | 提交或维护该属性定义的机构 | 用户录入 | 文本框 | 可选 |
| `language` | 定义语言,如 zh、en | 用户选择 | 下拉框 | 可选;建议 ISO 639-1 |
| `scientist` | 提交该属性定义的科学家或负责人 | 用户录入/人员选择 | 文本框/人员选择器 | 可选 |
| `status` | 属性状态,如 recommended、obsolete、legacy | 用户选择 | 下拉框 | 可选;推荐使用枚举 |
| `submission_timestamp` | 属性定义提交时间 | 系统默认当前时间,可手动调整 | 日期时间选择器 | 可选;新增默认当前时间 |
| `crop_id` | 适用作物 | 从 crop 选择 | 作物选择器 | 可选;若填写,下游材料应同 crop |
| `method_id` | 属性测定方法 | 从 method 选择 | 方法选择器 | 可选;若填写,属性值录入按该方法解释 |
| `ontology_id` | 所属本体 | 从 ontology 选择 | 本体选择器 | 可选 |
| `scale_id` | 值标尺/单位/有效值范围 | 从 scale 选择 | 标尺选择器 | 可选;若填写,属性值必须按 scale 校验 |
| `trait_id` | 关联性状 | 从 trait 选择 | 性状选择器 | 可选 |
| `attribute_category` | 属性分类,如 Morphological、Genetic、Quality | 用户选择/录入 | 下拉框/文本框 | 可选;建议字典化 |
| `code` | 属性代码,便于导入导出 | 用户录入 | 文本框 | 可选;建议唯一 |
| `datatype` | 属性值数据类型,如 text、numeric、date、boolean、categorical | 用户选择 | 下拉框 | 必填 |
| `description` | 属性解释 | 用户录入 | 多行文本 | 可选 |
| `name` | 属性名称 | 用户录入 | 文本框 | 必填;作为属性选择器展示名称 |
| `pui` | 属性永久标识 | 用户录入 | 文本框/URL 输入框 | 可选;建议唯一 |
| `uri` | 属性 URI | 用户录入 | URL 输入框 | 可选;校验 URL |
### 录入建议
- 属性定义页面本质是“属性字典配置”。
- 前端应根据 `datatype` 动态决定属性值录入控件:
- numeric数字输入框
- categorical下拉框
- date日期选择器
- boolean开关
- text文本框。
- 若绑定了 `scale_id`,则优先按 scale 的单位、上下限、有效分类值校验。
---
## 5.4 germplasm_attribute_value 属性值
### 业务说明
属性值是“某个 germplasm 在某个属性上的实际取值”。它不是属性定义,也不是 observation。它适合记录材料相对稳定、不强依赖环境的特征。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ----------------- | ------------------------------ | -------------------------------------- | ---------- | ---------------------------------------- |
| `id` | 属性值主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `determined_date` | 属性值被测定或确认的日期 | 用户录入 | 日期选择器 | 可选;多次测定时必须填写以区分记录 |
| `value` | 某个材料在某个属性上的实际取值 | 用户录入 | 动态控件 | 必填;按 attribute datatype / scale 校验 |
| `attribute_id` | 属性定义 | 从 germplasm_attribute_definition 选择 | 属性选择器 | 必选;必须存在 |
| `germplasm_id` | 所属材料 | 从 germplasm 选择 | 材料选择器 | 必选;必须存在 |
### 录入建议
- 推荐嵌入 Germplasm 详情页的“属性值”Tab。
- 支持批量导入,模板列建议为:`germplasm_id/germplasm_name``attribute_code/attribute_name``value``determined_date`
- 同一个 germplasm + attribute 可以允许多次测定,但页面必须显示测定日期、来源和最新值标记。
---
## 5.5 crossing_project 杂交项目
### 业务说明
`crossing_project` 是某个育种项目下的一组杂交任务集合。它不是一次杂交而是一个杂交工作台例如“2026 抗倒伏杂交项目”。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------- | ------------------ | ------------------ | ---------- | ----------------------------- |
| `id` | 杂交项目主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `description` | 杂交项目说明 | 用户录入 | 多行文本 | 可选 |
| `name` | 杂交项目名称 | 用户录入 | 文本框 | 必填;同一 program 下建议唯一 |
| `program_id` | 所属育种项目 | 从 program 选择 | 项目选择器 | 必选;必须存在 |
### 页面与交互
- 详情页应展示计划杂交、实际杂交、潜在亲本、后代材料、产生的 seed lot。
- 创建 cross 时应自动带入 crossing_project_id。
---
## 5.6 cross_entity 计划杂交 / 实际杂交
### 业务说明
`cross_entity` 统一承载计划杂交和实际杂交。通过 `planned` 字段区分计划与实际,通过 `planned_cross_id` 指向来源计划。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | ------------------------------------------- | ------------------------ | -------------- | --------------------------------------- |
| `id` | cross 主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `cross_type` | 杂交类型,如 biparental、self、backcross 等 | 用户选择 | 下拉框 | 可选;值来自枚举字典 |
| `name` | cross 名称,如 A × B、A/B、Cross-2026-001 | 用户录入或自动生成 | 文本框 | 必填;同一 crossing project 下建议唯一 |
| `planned` | 是否为计划杂交 | 页面根据入口自动设置 | 开关/分段控件 | 必填;计划杂交为 true实际杂交为 false |
| `status` | 状态,如 TODO、DONE、SKIPPED、FAILED | 用户选择/系统更新 | 下拉框 | 可选;计划杂交常用 TODO/DONE/SKIPPED |
| `crossing_project_id` | 所属杂交项目 | 从 crossing_project 选择 | 杂交项目选择器 | 必选 |
| `planned_cross_id` | 实际杂交来源的计划杂交 | 从 cross_entity 选择 | Cross 选择器 | 可选;不能选择自己;实际杂交建议填写 |
### 录入建议
- 页面上分成“计划杂交”和“实际杂交”两个入口,但后端都保存到 `cross_entity`
- 创建计划杂交时:`planned=true``planned_cross_id=null`
- 完成实际杂交时:`planned=false``planned_cross_id=原计划杂交 id`
- 亲本不要直接塞在 cross 主表字段中,应通过 `cross_parent` 维护,便于支持多亲本和 observation_unit 亲本来源。
---
## 5.7 cross_parent 杂交亲本
### 业务说明
`cross_parent` 表示某个 cross 的亲本。亲本可以来自 `germplasm`,也可以来自某个 `observation_unit`,例如田间某一株实际被选作父本/母本。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | --------------------------------------------------- | ---------------------------------- | ----------------- | ------------------------------------- |
| `id` | 亲本记录主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `parent_type` | 亲本角色,如 MALE、FEMALE、SELF、POPULATION、CLONAL | 用户选择 | 下拉框 | 必填;使用枚举 |
| `cross_id` | 所属 cross | 从 cross_entity 选择或由详情页带入 | Cross 选择器/隐藏 | 必选 |
| `crossing_project_id` | 所属 crossing project | 由 cross 自动带出 | 只读/隐藏 | 可选;如填写必须与 cross 一致 |
| `germplasm_id` | 亲本材料 | 从 germplasm 选择 | 材料选择器 | 与 `observation_unit_id` 至少一个必填 |
| `observation_unit_id` | 亲本观测单元 | 从 observation_unit 选择 | 观测单元选择器 | 与 `germplasm_id` 至少一个必填 |
### 录入建议
- 在 Cross 详情页内嵌“亲本列表”。
- 常见快捷录入Parent1 / Parent2。
- 对于田间选株杂交,优先记录 observation_unit_id同时可带出 germplasm_id保证可追溯到具体植株。
---
## 5.8 pedigree_node 系谱节点
### 业务说明
`pedigree_node` 是系谱图中的节点,通常对应一个 germplasm。它用于描述材料在系谱树中的位置不等同于一次杂交记录。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| --------------------- | --------------------- | ------------------------ | -------------- | ----------------------------------------- |
| `id` | 系谱节点主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `crossing_year` | 亲本最初杂交年份 | 用户录入 | 年份选择器 | 可选;四位年份 |
| `family_code` | 家系编号 | 用户录入 | 文本框 | 可选;同一 crossing_project 下建议唯一 |
| `pedigree_string` | 系谱字符串,如 A/B//C | 用户录入/系统生成 | 文本框 | 可选;建议支持 Purdy notation |
| `crossing_project_id` | 产生该节点的杂交项目 | 从 crossing_project 选择 | 杂交项目选择器 | 可选 |
| `germplasm_id` | 该系谱节点对应的材料 | 从 germplasm 选择 | 材料选择器 | 建议必填;同一 germplasm 不建议重复建节点 |
### 录入建议
- Germplasm 详情页提供“系谱”Tab。
- 支持两种维护方式:树图拖拽维护、表格维护节点和边。
- 如果 cross 完成后产生后代 germplasm应自动或半自动创建 pedigree_node。
---
## 5.9 pedigree_edge 系谱边
### 业务说明
`pedigree_edge` 是系谱图中的边,描述节点之间的父子、同胞等关系。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------- | ------------------------------------------ | --------------------- | ---------- | ------------------------------------ |
| `id` | 系谱边主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `edge_type` | 边类型,如 parent、child、sibling | 用户选择 | 下拉框 | 必填 |
| `parent_type` | 如果是亲本关系,标识 MALE、FEMALE、SELF 等 | 用户选择 | 下拉框 | 可选;当 edge_type=parent 时建议必填 |
| `connceted_node_id` | 被连接节点 | 从 pedigree_node 选择 | 节点选择器 | 必选 |
| `this_node_id` | 当前节点 | 从 pedigree_node 选择 | 节点选择器 | 必选;不能等于 connected node |
### 录入建议
- 前端展示时不要暴露“this_node_id / connected_node_id”这种技术词应该显示为“当前材料”和“关联材料”。
- 添加父本/母本时,系统自动创建 edge_type=parent。
- 需要避免明显循环,例如 A 是 B 的父本,同时 B 又是 A 的父本。
---
## 5.10 seed_lot 种子批次
### 业务说明
`seed_lot` 是实物库存批次,描述某一批种子当前有多少、放在哪里、属于哪个项目。它不是 germplasm 身份;同一个 germplasm 可以有多个 seed_lot。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------- | ---------------------------------------------------- | --------------------- | ------------------- | ----------------------------- |
| `id` | SeedLot 主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `amount` | 当前库存数量,可以是粒数、重量、株数等 | 用户录入/交易自动更新 | 数字输入框 | 必填;非负;交易后自动更新 |
| `created_date` | 批次创建时间 | 系统默认,可导入 | 日期时间选择器/只读 | 默认当前时间 |
| `description` | 批次说明 | 用户录入 | 多行文本 | 可选 |
| `last_updated` | 最后更新时间,包含交易变化 | 系统自动更新 | 只读 | 不允许手动改 |
| `name` | 批次名称,如 华占-2026-荆门-扩繁批 | 用户录入或自动生成 | 文本框 | 必填;同一 program 下建议唯一 |
| `source_collection` | 原始来源 collection如野外采集、nursery、种质库集合 | 用户录入 | 文本框 | 可选 |
| `storage_location` | 具体库位描述,如 冰箱A-2层-盒03 | 用户录入 | 文本框 | 可选 |
| `units` | 数量单位,如 seeds、g、kg、plants | 用户选择 | 下拉框/文本框 | 必填;交易单位需一致或可换算 |
| `location_id` | 库存所在地点 | 从 location 选择 | 地点选择器 | 可选 |
| `program_id` | 所属项目 | 从 program 选择 | 项目选择器 | 可选;用于项目库存筛选 |
### 录入建议
- 创建 seed_lot 后必须进入“批次组成”Tab至少录入一条 `seed_lot_content_mixture`
- 普通用户不要直接编辑 amountamount 应通过入库、出库、转移、分装等交易动作更新。
- 支持库存状态:充足、低库存、耗尽,可由 amount 和阈值计算。
---
## 5.11 seed_lot_content_mixture 批次组成
### 业务说明
`seed_lot_content_mixture` 描述一个 seed_lot 由哪些材料或 cross 组成。单一材料批次也需要有一条组成记录,比例为 100%。混合批次则多条记录占比合计为 100%。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| -------------------- | ----------------------------- | -------------------- | ------------------- | ---------------------------------------- |
| `id` | 批次组成主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `mixture_percentage` | 该材料或 cross 在批次中的占比 | 用户录入 | 百分比输入框 | 0 到 100同一 seed lot 总和建议等于 100 |
| `cross_id` | 来源 cross | 从 cross_entity 选择 | Cross 选择器 | 与 `germplasm_id` 至少一个必填 |
| `germplasm_id` | 来源 germplasm | 从 germplasm 选择 | 材料选择器 | 与 `cross_id` 至少一个必填 |
| `seed_lot_id` | 所属 seed lot | 由详情页带入或选择 | SeedLot 选择器/隐藏 | 必选 |
### 录入建议
- 新建 seed_lot 时,如果用户选择了单个 germplasm系统自动生成一条 mixture`germplasm_id=所选材料``mixture_percentage=100`
- 如果来源是某次杂交产生的种子,优先填写 `cross_id`
- 如果既能追溯 cross 又能追溯 germplasm可按系统设计决定是否允许同时填写若允许同时展示“来源杂交”和“当前材料身份”。
---
## 5.12 seed_lot_transaction 批次流转
### 业务说明
`seed_lot_transaction` 记录库存变化。它不应该由用户像普通表单一样手动维护,而应该由“入库、出库、转移、分装、合并、消耗”等业务动作自动生成。
### 字段说明
| 字段 | 业务意义 | 录入方式 | 控件建议 | 校验规则 |
| ------------------ | -------------------------------------------- | ----------------------- | ------------------- | ------------------------------------------------- |
| `id` | 流转记录主键 | 系统生成 | 隐藏/只读 | 必填、唯一 |
| `auth_user_id` | 数据所属用户或租户 | 登录上下文自动写入 | 隐藏 | 不允许手填 |
| `amount` | 流转数量 | 用户在业务动作中录入 | 数字输入框 | 必填;大于 0 |
| `description` | 流转说明,如用于某 study、分装原因、报废原因 | 用户录入 | 多行文本 | 可选;出库/报废建议必填 |
| `timestamp` | 流转发生时间 | 默认当前时间,可调整 | 日期时间选择器 | 必填 |
| `units` | 流转单位 | 默认继承 seed_lot.units | 下拉框/只读 | 必填;需与 seed_lot 单位一致或有换算关系 |
| `from_seed_lot_id` | 来源批次 | 按动作自动设置 | SeedLot 选择器/隐藏 | 与 `to_seed_lot_id` 至少一个存在 |
| `to_seed_lot_id` | 目标批次 | 按动作自动设置 | SeedLot 选择器/隐藏 | 与 `from_seed_lot_id` 至少一个存在;不能等于 from |
### 业务动作映射
| 动作 | from_seed_lot_id | to_seed_lot_id | amount 对库存影响 |
| --------- | ---------------- | -------------- | -------------------------------------------- |
| 入库 | 空 | 目标批次 | 目标批次增加 |
| 出库 | 来源批次 | 空 | 来源批次减少 |
| 转移 | 来源批次 | 目标批次 | 来源减少,目标增加 |
| 分装 | 原批次 | 新批次 | 原批次减少,新批次增加 |
| 合并 | 多个来源批次 | 目标批次 | 来源减少,目标增加;可能生成多条 transaction |
| 消耗/报废 | 来源批次 | 空 | 来源减少,并记录原因 |
### 验收标准
1. amount 必须大于 0。
2. 出库/消耗时amount 不得超过来源批次当前库存。
3. from 和 to 不能相同。
4. transaction 创建后应自动更新 seed_lot.amount 和 last_updated。
5. 已生成的 transaction 原则上不允许随意修改;如需纠错,应通过反向交易或更正记录处理。
---
# 6. 跨表联动与关键校验
## 6.1 选择器联动
| 场景 | 联动规则 |
| ------------------------- | ------------------------------------------------------------ |
| 创建 germplasm | 必须先选择 cropbreeding_method 可选 |
| 创建 attribute definition | crop 可选;若选择 trait/method/scale/ontology则必须引用存在记录 |
| 创建 attribute value | 选择 germplasm 后attribute 选择器优先展示同 crop 或未限定 crop 的属性 |
| 创建 crossing project | 必须选择 program |
| 创建 cross | 必须先选择 crossing_project计划杂交和实际杂交使用不同入口 |
| 创建 cross parent | 从 cross 详情页进入时自动带出 cross 和 crossing_project |
| 创建 seed lot | 可选择 program、location保存后必须维护 content mixture |
| 创建 transaction | 从 seed lot 详情页进入时自动带出 from/to seed lot |
## 6.2 删除规则
| 对象 | 删除限制 |
| -------------------- | ------------------------------------------------------------ |
| breeding_method | 已被 germplasm 引用时不可删除 |
| germplasm | 已被 attribute value、cross parent、seed lot mixture、pedigree、observation unit 引用时不可删除 |
| attribute definition | 已有 attribute value 时不可删除 |
| crossing_project | 已有 cross / cross parent / pedigree node 时不可删除 |
| cross_entity | 已有 parent、seed lot mixture、observation unit 引用时不可删除 |
| seed_lot | 已有 mixture、transaction、observation unit 引用时不可删除 |
| transaction | 原则上不可物理删除;只能冲销或作废 |
## 6.3 批量导入要求
### Germplasm 导入
必需列建议:
```text
crop_id 或 crop_name
germplasm_name 或 default_display_name
```
强烈建议列:
```text
accession_number
germplasmpui
breeding_method_name
country_of_origin_code
genus
species
seed_source
```
### SeedLot 导入
必需列建议:
```text
seed_lot_name
amount
units
germplasm_id/germplasm_name 或 cross_id/cross_name
mixture_percentage
```
### Attribute Value 导入
必需列建议:
```text
germplasm_id 或 germplasm_name
attribute_id 或 attribute_name/code
value
```
可选列:
```text
determined_date
source
remark
```
导入必须先预校验,错误报告至少包含:行号、字段、错误原因、建议修复方式。
---
# 7. 后端接口建议
## 7.1 主数据接口
```text
GET /germplasm
POST /germplasm
GET /germplasm/{id}
PUT /germplasm/{id}
DELETE /germplasm/{id}
GET /breeding-methods
POST /breeding-methods
GET /germplasm-attributes
POST /germplasm-attributes
GET /germplasm/{id}/attribute-values
POST /germplasm/{id}/attribute-values
GET /crossing-projects
POST /crossing-projects
GET /crossing-projects/{id}/crosses
GET /crosses
POST /crosses
GET /crosses/{id}/parents
POST /crosses/{id}/parents
GET /seed-lots
POST /seed-lots
GET /seed-lots/{id}/mixtures
POST /seed-lots/{id}/mixtures
GET /seed-lots/{id}/transactions
POST /seed-lots/{id}/transactions
```
## 7.2 选择器接口
```text
GET /selectors/crops
GET /selectors/breeding-methods
GET /selectors/germplasm?cropId=&keyword=
GET /selectors/germplasm-attributes?cropId=&datatype=&keyword=
GET /selectors/crossing-projects?programId=&keyword=
GET /selectors/crosses?crossingProjectId=&planned=&keyword=
GET /selectors/seed-lots?programId=&locationId=&keyword=
GET /selectors/observation-units?studyId=&germplasmId=&keyword=
```
---
# 8. 测试验收清单
1. 创建 germplasm 时,未选择 crop 不允许保存。
2. `germplasm_name``default_display_name` 都为空时不允许保存。
3. `germplasmpui` 重复时提示唯一性冲突。
4. attribute value 的 value 必须按 attribute datatype / scale 校验。
5. 创建 cross 时必须选择 crossing project。
6. 实际杂交选择 planned_cross_id 时不能选择自身。
7. cross parent 必须选择 parent_type。
8. cross parent 的 germplasm_id 和 observation_unit_id 至少填写一个。
9. seed lot 的 amount 不允许小于 0。
10. seed lot 的 units 必填。
11. seed lot content mixture 的 percentage 必须在 0 到 100 之间。
12. 同一 seed lot 的 mixture_percentage 总和不为 100 时,保存前应提示或禁止保存,具体取决于业务配置。
13. 出库数量不能超过当前库存。
14. transaction 创建后自动更新 seed_lot.amount。
15. 已有关联下游数据的 germplasm、cross、seed_lot 不允许物理删除。