# Core 模块数据流与表关系

本文档分析 `brapi-java` 项目 core 模块的数据录入顺序、主表关系，以及初始化脚本中的实际数据流。

## 结论

Core 模块的数据主线是：

```text
crop -> person -> program -> location -> trial -> season -> study -> study 附属信息
```

`list` 是相对独立的列表能力，可以较早录入；如果需要绑定列表所有人，则依赖 `person`。

初始化脚本实际执行顺序是：

```text
R__init_data_01_crops.sql
R__init_data_02_lists.sql
R__init_data_03_locations.sql
R__init_data_04_people.sql
R__init_data_05_programs.sql
R__init_data_06_trials.sql
R__init_data_07_seasons.sql
R__init_data_08_studies.sql
```

其中 `R__init_data_05_programs.sql` 会插入 program 负责人到 `person` 表，并回填部分 `location.program_id/crop_id`。

## 核心表说明

| 表 | 作用 | 主要上游依赖 | 主要下游 |
| --- | --- | --- | --- |
| `crop` | 作物字典，Core 主根数据之一 | 无 | `program`、`location`、`trial`、`study` |
| `person` | 人员、联系人、负责人 | 无 | `program.lead_person_id`、`trial_contact`、`study_contact`、`list.list_owner_person_id` |
| `program` | 育种项目/业务项目 | `crop`、可选 `person` | `trial`、`study`、`location` |
| `location` | 地点/试验点 | 可选 `crop`、`program`、父级 `location`、`geojson` | `study` |
| `trial` | 试验批次/试验项目 | `crop`、`program` | `study`、`trial_contact`、`trial_publication`、`trial_dataset_authorship` |
| `season` | 季节/年度区间字典 | 无 | `study_season`、部分 observation |
| `study` | 具体研究/试验实施单元 | `crop`、`program`、`trial`、`location` | `study_contact`、`study_season`、`study_data_link`、`study_observation_level` 等 |
| `list` | 通用列表 | 可选 `person` | `list_item` |
| `list_item` | 列表明细项 | `list` | 无 |

## 建议录入顺序

### 1. 录入基础字典

先录入 `crop` 和 `person`。

`crop` 是作物维度根数据，后续 `program`、`trial`、`study` 都会挂到它下面。`person` 是人员基础资料，后续会作为项目负责人、试验联系人、研究联系人、列表负责人使用。

### 2. 录入地点

录入 `location`，如果地点有坐标，需要先录入 `geojson` 和 `coordinate`。

地点可以先不绑定 `program/crop`，初始化脚本里就是先插入地点，再在 program 初始化阶段回填 `program_id` 和 `crop_id`。

### 3. 录入项目 Program

录入 `program` 时需要已有 `crop`。如果有负责人，需要已有 `person`。

程序层面 `ProgramEntity.setCrop(...)` 直接绑定作物；后续 trial/study 设置 program 时，会同步继承 program 的 crop。

### 4. 录入 Trial

录入 `trial` 时需要已有 `program` 和 `crop`。

`trial` 还可以同时录入：

```text
trial_contact
trial_dataset_authorship
trial_publication
trial_additional_info
trial_external_references
```

其中 `trial_contact` 是 `trial` 和 `person` 的多对多关系表。

### 5. 录入 Season

录入 `season`。它本身相对独立，但后续 `study` 会通过 `study_season` 关联多个 season。

### 6. 录入 Study

录入 `study` 时通常需要已有：

```text
crop
program
trial
location
```

`study` 是 core 模块向 pheno/geno 数据扩展的关键节点。后续 observation、observation_unit、sample、plate、variantset 等很多模块都会引用 `study`。

### 7. 录入 Study 附属信息

录入 study 后，再录入依赖 `study_id` 的附属表：

```text
study_contact
study_data_link
study_environment_parameter
study_experimental_design
study_growth_facility
study_last_update
study_observation_level
study_season
study_variable
study_additional_info
study_external_references
```

## Core 数据流图

```mermaid
flowchart TD
    A["1. crop 作物字典"] --> C["3. program 项目"]
    B["2. person 人员"] --> C
    B --> L["list 列表负责人，可选"]
    L --> LI["list_item 列表项"]

    G["geojson / coordinate 坐标"] --> D["2. location 地点"]
    A --> D
    C --> D
    D --> E["6. study 研究"]

    C --> F["4. trial 试验"]
    A --> F
    B --> FC["trial_contact 试验联系人"]
    F --> FC
    F --> FP["trial_publication / trial_dataset_authorship"]

    S["5. season 季节"] --> SS["study_season 研究季节"]
    F --> E
    C --> E
    A --> E
    E --> SS
    E --> SC["study_contact 研究联系人"]
    B --> SC
    E --> SA["study_data_link / environment / design / growth_facility / last_update / observation_level"]

    E --> P1["pheno: observation_unit / observation"]
    E --> G1["geno: sample / plate / variantset"]
```

## Core ER 关系图

```mermaid
erDiagram
    crop ||--o{ program : "crop_id"
    crop ||--o{ location : "crop_id"
    crop ||--o{ trial : "crop_id"
    crop ||--o{ study : "crop_id"

    person ||--o{ program : "lead_person_id"
    person ||--o{ trial_contact : "person_db_id"
    person ||--o{ study_contact : "person_db_id"
    person ||--o{ list : "list_owner_person_id"

    program ||--o{ location : "program_id"
    program ||--o{ trial : "program_id"
    program ||--o{ study : "program_id"

    location ||--o{ location : "parent_location_id"
    location ||--o{ study : "location_id"

    trial ||--o{ study : "trial_id"
    trial ||--o{ trial_contact : "trial_db_id"
    trial ||--o{ trial_publication : "trial_id"
    trial ||--o{ trial_dataset_authorship : "trial_id"

    study ||--o{ study_contact : "study_db_id"
    study ||--o{ study_season : "study_db_id"
    season ||--o{ study_season : "season_db_id"

    study ||--o{ study_data_link : "study_id"
    study ||--o{ study_environment_parameter : "study_id"
    study ||--o{ study_experimental_design : "study_id"
    study ||--o{ study_growth_facility : "study_id"
    study ||--o{ study_last_update : "study_id"
    study ||--o{ study_observation_level : "study_id"

    list ||--o{ list_item : "list_id"
```

## API 与表的对应关系

| API | 主表 | 说明 |
| --- | --- | --- |
| `GET /brapi/v2/commoncropnames` | `crop` | 查询作物名称列表 |
| `GET/POST/PUT /brapi/v2/people` | `person` | 人员查询、新增、修改；无删除接口 |
| `GET/POST/PUT /brapi/v2/programs` | `program` | 项目依赖 crop，可关联 lead person |
| `GET/POST/PUT /brapi/v2/locations` | `location` | 地点可关联 crop、program、parent location、geojson |
| `GET/POST/PUT /brapi/v2/trials` | `trial` | 试验依赖 program/crop，可关联 contacts/publications |
| `GET/PUT /brapi/v2/seasons` | `season` | 季节字典 |
| `GET/POST/PUT /brapi/v2/studies` | `study` | 研究依赖 trial/program/crop/location |
| `GET/POST/PUT /brapi/v2/lists` | `list`、`list_item` | 列表及列表项 |

## 关键注意点

1. `crop` 是最重要的根字典之一，许多业务表都有 `crop_id`。
2. `program` 是承上启下的业务节点，它依赖 `crop`，并被 `trial`、`study`、`location` 引用。
3. `trial` 是 study 的上级试验组织，`study` 是后续表型、基因型数据的核心入口。
4. `person` 与 `trial/study` 是多对多关系，通过 `trial_contact`、`study_contact` 连接。
5. `study_season` 是 `study` 和 `season` 的多对多关系。
6. `additional_info` 和 `external_reference` 是通用扩展表，core 主表通过各自的 `*_additional_info`、`*_external_references` 关联它们。
7. 初始化脚本中 `list` 早于 `person` 插入，是因为初始 list 数据主要使用文本 owner 字段；如果业务上要设置 `list_owner_person_id`，应先有 `person`。

