# 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`。
- 普通用户不要直接编辑 amount；amount 应通过入库、出库、转移、分装等交易动作更新。
- 支持库存状态：充足、低库存、耗尽，可由 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            | 必须先选择 crop；breeding_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 不允许物理删除。

