-- ============================================================ -- 桃育种系统 - 一期业务表建表 SQL(breeding 全量 14 域) -- 依据: 后端 ORM 模型 (backend/app/api/v1/module_bre/**/model.py) -- 对齐 doc/桃育种系统业务功能规划报告.md 第九节(2026-07-28 实际落地) -- 说明: -- 1. bre_germplasm 等表由 create_all 建;本文件为可读 schema 参考。 -- 2. 审计字段(id/uuid/is_deleted/created_time/updated_time/deleted_time/ -- created_id/updated_id/deleted_id)由基类 ModelMixin/UserMixin 提供。 -- 3. 外键统一引用 sys_user(id) ON DELETE SET NULL(审计人); -- 业务外键引用本文件内表,统一 ON DELETE CASCADE(级联删除)。 -- 4. 状态/类别字段以 varchar 存字典存储值(英码 dict_value,如 common/strong/alive), -- 展示中文 dict_label;[字典: ] 标注的字段其取值来自 sys_dict,种子见 -- bre_dict.sql,导入经 DictLabelResolver 翻译、前端经 useDictStore 取 label; -- [字典: 待补] 表示模型标注为字典字段但尚无种子 SQL,取值待定。 -- 5. 育种目标独立成表 bre_target(主数据);杂交组合单选引用其一, -- 以便后期按"组合→目标→目标性状阈值→单株达标判定"统计每组合达标率。 -- 6. 育种单株独立成表 bre_tree(新增实体);tree_evaluation / -- tree_photo / selection_result 经 tree_id 外键关联,删树级联删下游三表。 -- 7. 人员独立成表 bre_personnel(方案B);5 个业务域经 -- bre_personnel_id 外键引用(授粉人/定植人/育苗人/评价人/种子处理人)。 -- 8. 无 status 字段的表,model 中已覆盖 __table_args__ 去掉 status 索引 -- (仅保留 (created_time, is_deleted) 复合索引用于数据权限过滤)。 -- 9. 日期字段以 varchar(20) 存文本日期(如 '2026-07-28'),非 timestamptz。 -- ============================================================ -- ============================================================ -- 模块1: 亲本资源管理 -- ============================================================ -- 表: bre_germplasm (亲本资源) -- 设计说明: 保存育种用种质/品种档案,作为杂交组合的母本与父本来源。 -- 与其它表关系: -- * 上游: 无 -- * 下游: 被 cross_combination(female_parent_id/male_parent_id) 引用; -- 被 bre_germplasm_photo(独立文件) 经 germplasm_id 引用 -- 字典来源字段: variety_type(变种类型), firmness(硬度), maturity_period(成熟期:早/中/晚), -- flowering_period(花期) —— 均 [字典],见 bre_dict.sql -- 逻辑关系: 删除种质 → 级联删除其照片子表;作为母/父本被组合引用时随组合级联删除 CREATE TABLE IF NOT EXISTS bre_germplasm ( cultivar_name varchar(100) NOT NULL -- 品种/种质名称, variety_type varchar(20) -- 变种类型(普通桃/油桃/蟠桃/油蟠桃/黄肉) [字典: variety_type], origin varchar(200) -- 来源, preservation_site varchar(200) -- 保存地, avg_fruit_weight numeric(8,2) -- 平均果重(g), ssc numeric(4,1) -- 可溶性固形物(%), firmness varchar(20) -- 硬度 [字典: firmness], maturity_period varchar(20) -- 成熟期(早/中/晚) [字典: maturity_period], flowering_period varchar(20) -- 花期 [字典: flowering_period], chilling_requirement int -- 需冷量(h), disease_resistance text -- 抗病性描述, can_be_female boolean NOT NULL DEFAULT false -- 可作母本, can_be_male boolean NOT NULL DEFAULT false -- 可作父本, pedigree_note text -- 系谱备注, photo_path varchar(500) -- 照片地址(图片URL), CONSTRAINT bre_germplasm_uuid_key UNIQUE (uuid), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_germplasm_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_germplasm IS '亲本资源表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_germplasm_created_deleted ON bre_germplasm (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uniq_bre_germplasm_cultivar_name ON bre_germplasm (cultivar_name) WHERE (is_deleted = false); CREATE INDEX IF NOT EXISTS ix_bre_germplasm_cultivar_name ON bre_germplasm (cultivar_name); CREATE INDEX IF NOT EXISTS ix_bre_germplasm_is_deleted ON bre_germplasm (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_germplasm_variety_type ON bre_germplasm (variety_type); -- ============================================================ -- 模块2: 基地/试验地管理 -- ============================================================ -- 表: bre_site (基地/试验地) -- 设计说明: 试验基地/试验站主数据,定植与授粉的地点来源。 -- 与其它表关系: -- * 上游: 无 -- * 下游: 被 bre_plot(site_id) 引用 -- 字典来源字段: eco_type(生态区类型:华北/西北/华东/西南/东北/华南) [字典],见 bre_dict.sql -- 逻辑关系: 删除基地 → 级联删除其下所有地块 CREATE TABLE IF NOT EXISTS bre_site ( site_name varchar(100) NOT NULL -- 基地/试验地名称, address varchar(255) -- 详细地址, area float -- 基地面积(亩), longitude float -- 经度, latitude float -- 纬度, eco_type varchar(50) -- 生态区类型(华北/西北/华东/...) [字典: eco_type], remark text -- 备注, CONSTRAINT bre_site_site_name_key UNIQUE (site_name), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_site_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_site IS '基地/试验地管理表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_site_created_deleted ON bre_site (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_site_created_id ON bre_site (created_id); CREATE INDEX IF NOT EXISTS ix_bre_site_created_time ON bre_site (created_time); CREATE INDEX IF NOT EXISTS ix_bre_site_deleted_id ON bre_site (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_site_id ON bre_site (id); CREATE INDEX IF NOT EXISTS ix_bre_site_is_deleted ON bre_site (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_site_updated_id ON bre_site (updated_id); -- 表: bre_plot (区块: 基地内区块划分) -- 设计说明: 基地内区块划分,作为单株定植的网格位置。 -- 与其它表关系: -- * 上游: 引用 bre_site(site_id) -- * 下游: 被 pollination(plot_id)/planting(plot_id)/tree(plot_id) 引用 -- 字典来源字段: row_orientation(行向:南北行/东西行) [字典],见 bre_dict.sql -- 逻辑关系: 删除地块 → 级联删除引用该地块的授粉/定植/单株记录 CREATE TABLE IF NOT EXISTS bre_plot ( site_id int NOT NULL -- 所属基地, plot_code varchar(50) NOT NULL -- 区块编号/名称, row_orientation varchar(20) -- 行向(南北行/东西行) [字典: row_orientation], row_count int -- 行数, col_count int -- 每行株数, grid_note text -- 株行距/网格说明, area float -- 地块面积(亩), CONSTRAINT fk_bre_plot_site_id FOREIGN KEY (site_id) REFERENCES bre_site (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_plot_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_plot IS '基地内区块划分表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_plot_created_deleted ON bre_plot (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uniq_bre_plot_site_code ON bre_plot (site_id, plot_code) WHERE (is_deleted = false); CREATE INDEX IF NOT EXISTS ix_bre_plot_created_id ON bre_plot (created_id); CREATE INDEX IF NOT EXISTS ix_bre_plot_created_time ON bre_plot (created_time); CREATE INDEX IF NOT EXISTS ix_bre_plot_deleted_id ON bre_plot (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_plot_id ON bre_plot (id); CREATE INDEX IF NOT EXISTS ix_bre_plot_is_deleted ON bre_plot (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_plot_site ON bre_plot (site_id); CREATE INDEX IF NOT EXISTS ix_bre_plot_site_id ON bre_plot (site_id); CREATE INDEX IF NOT EXISTS ix_bre_plot_updated_id ON bre_plot (updated_id); -- ============================================================ -- 模块3: 人员花名册 -- ============================================================ -- 表: bre_personnel (人员花名册,独立人员表/方案B) -- 设计说明: 记录参与育种的人员;被 5 个业务域经 bre_personnel_id 引用, -- 作为"干活的人"(授粉人/定植人/育苗人/评价人/种子处理人)。 -- 与其它表关系: -- * 上游: 无 -- * 下游: 被 pollination/planting/seedling/tree_evaluation/seed_treatment -- 的 bre_personnel_id 引用 -- 字典来源字段: gender(性别:男/女) [字典], role(角色:育种专家/技术员/管理员) [字典],见 bre_dict.sql -- 逻辑关系: 删除人员 → 级联删除各业务记录中该人员引用(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_personnel ( name varchar(100) NOT NULL -- 姓名, gender varchar(50) -- 性别(男/女) [字典: gender], role varchar(50) -- 角色(育种专家/技术员/管理员) [字典: personnel_role], phone varchar(100) -- 联系电话, organization varchar(100) -- 所属单位, join_date varchar(20) -- 入职日期, remark text -- 备注, id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_personnel_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_personnel IS '人员花名册表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_personnel_created_deleted ON bre_personnel (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uniq_bre_personnel_name ON bre_personnel (name) WHERE (is_deleted = false); CREATE INDEX IF NOT EXISTS ix_bre_personnel_created_id ON bre_personnel (created_id); CREATE INDEX IF NOT EXISTS ix_bre_personnel_created_time ON bre_personnel (created_time); CREATE INDEX IF NOT EXISTS ix_bre_personnel_deleted_id ON bre_personnel (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_personnel_id ON bre_personnel (id); CREATE INDEX IF NOT EXISTS ix_bre_personnel_is_deleted ON bre_personnel (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_personnel_updated_id ON bre_personnel (updated_id); -- ============================================================ -- 模块4: 育种目标(主数据) -- ============================================================ -- 表: bre_target (育种目标主数据) -- 设计说明: 预置"6大品种系列"(大果型/早熟/黄肉/油桃/蟠桃/加工型)等目标,由育种家维护; -- 杂交组合单选引用其一,作为该组合达标率统计的统一基准。 -- 与其它表关系: -- * 上游: 无 -- * 下游: 被 cross_combination(bre_target_id) 引用 -- 字典来源字段: series(系列/品系) [字典], is_preset(是否预设:1/0) [字典],见 bre_dict.sql -- 逻辑关系: 删除目标 → 级联删除引用它的杂交组合 CREATE TABLE IF NOT EXISTS bre_target ( target_name varchar(100) NOT NULL -- 目标名称,如"优质大果型", series varchar(100) -- 系列/品系 [字典: series], description text -- 目标说明/关键性状描述, is_preset varchar(50) -- 是否预设(1/0) [字典: is_preset], remark text -- 备注, id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_target_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_target IS '育种目标主数据表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_target_created_deleted ON bre_target (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_target_created_id ON bre_target (created_id); CREATE INDEX IF NOT EXISTS ix_bre_target_created_time ON bre_target (created_time); CREATE INDEX IF NOT EXISTS ix_bre_target_deleted_id ON bre_target (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_target_id ON bre_target (id); CREATE INDEX IF NOT EXISTS ix_bre_target_is_deleted ON bre_target (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_target_updated_id ON bre_target (updated_id); -- ============================================================ -- 模块5: 组合选配 -- ============================================================ -- 表: bre_cross_combination (杂交组合) —— 全模块关系枢纽 -- 设计说明: 记录母本/父本/育种目标/杂交方式;下游授粉/种子/育苗/定植/单株 -- 均挂靠本表 combination_id,是整条育种管线的核心枢纽。 -- 与其它表关系: -- * 上游: 引用 bre_target(bre_target_id)、bre_germplasm(female_parent_id/male_parent_id) -- * 下游: 被 pollination/seed_treatment/seedling/planting/tree/tree_evaluation/ -- tree_photo/selection_result 的 combination_id 引用(共 8 张表) -- 字典来源字段: cross_method(杂交方式:人工杂交/自然授粉/回交) [字典],见 bre_dict.sql -- 逻辑关系: 删除组合 → 级联删除其下全部 8 张下游业务表记录 CREATE TABLE IF NOT EXISTS bre_cross_combination ( combination_code varchar(100) NOT NULL -- 组合编号 YY+3位序号(自动生成), cross_year int -- 杂交年份, bre_target_id int NOT NULL -- 育种目标(单选,主数据), female_parent_id int -- 母本, male_parent_id int -- 父本, cross_method varchar(50) -- 杂交方式(人工杂交/自然授粉/回交) [字典: cross_method], cross_date varchar(20) -- 杂交日期, seed_count int -- 获种数, remark text -- 备注, CONSTRAINT fk_bre_cross_combination_bre_target_id FOREIGN KEY (bre_target_id) REFERENCES bre_target (id), CONSTRAINT fk_bre_cross_combination_female_parent_id FOREIGN KEY (female_parent_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_cross_combination_male_parent_id FOREIGN KEY (male_parent_id) REFERENCES bre_germplasm (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_cross_combination_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_cross_combination IS '杂交组合选配表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_created_deleted ON bre_cross_combination (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uniq_bre_cross_combination_code ON bre_cross_combination (combination_code) WHERE (is_deleted = false); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_bre_target_id ON bre_cross_combination (bre_target_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_created_id ON bre_cross_combination (created_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_created_time ON bre_cross_combination (created_time); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_deleted_id ON bre_cross_combination (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_female ON bre_cross_combination (female_parent_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_female_parent_id ON bre_cross_combination (female_parent_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_id ON bre_cross_combination (id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_is_deleted ON bre_cross_combination (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_male ON bre_cross_combination (male_parent_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_male_parent_id ON bre_cross_combination (male_parent_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_target ON bre_cross_combination (bre_target_id); CREATE INDEX IF NOT EXISTS ix_bre_cross_combination_updated_id ON bre_cross_combination (updated_id); -- ============================================================ -- 模块6: 杂交授粉 -- ============================================================ -- 表: bre_pollination (授粉记录) -- 设计说明: 杂交授粉过程记录,挂靠杂交组合与试验地块。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、plot(plot_id)、personnel(bre_personnel_id 授粉人) -- * 下游: 无 -- 字典来源字段: 无(本表未设字典字段) -- 逻辑关系: 删除组合/地块/授粉人 → 级联删除本记录(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_pollination ( combination_id int NOT NULL -- 所属组合, plot_id int -- 试验地块, pollination_date varchar(20) -- 授粉日期, flower_count int -- 花朵数, effective_count int -- 有效坐果数, pollinator varchar(100), remark text -- 备注, bre_personnel_id int -- 授粉人, CONSTRAINT fk_bre_pollination_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_pollination_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_pollination_plot_id FOREIGN KEY (plot_id) REFERENCES bre_plot (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_pollination_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_pollination IS '杂交授粉记录表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_pollination_created_deleted ON bre_pollination (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_pollination_bre_personnel_id ON bre_pollination (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_combination ON bre_pollination (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_combination_id ON bre_pollination (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_created_id ON bre_pollination (created_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_created_time ON bre_pollination (created_time); CREATE INDEX IF NOT EXISTS ix_bre_pollination_deleted_id ON bre_pollination (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_id ON bre_pollination (id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_is_deleted ON bre_pollination (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_pollination_personnel ON bre_pollination (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_plot ON bre_pollination (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_plot_id ON bre_pollination (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_pollination_updated_id ON bre_pollination (updated_id); -- ============================================================ -- 模块7: 种子处理 -- ============================================================ -- 表: bre_seed_treatment (种子处理) -- 设计说明: 采果后种子处理(沙藏/胚培等)记录。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、personnel(bre_personnel_id 种子处理人) -- * 下游: 无 -- 字典来源字段: treatment_method(处理方式:沙藏/层积/低温冷藏/常温) [字典],见 bre_dict.sql -- 逻辑关系: 删除组合/处理人 → 级联删除本记录(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_seed_treatment ( combination_id int NOT NULL -- 所属组合, treatment_method varchar(50) -- 处理方式(沙藏/层积/低温冷藏/常温) [字典: seed_treatment_method], treatment_start varchar(20) -- 处理开始日期, treatment_end varchar(20) -- 处理结束日期, germination_rate float -- 发芽率(%), remark text -- 备注, bre_personnel_id int -- 种子处理人, CONSTRAINT fk_bre_seed_treatment_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_seed_treatment_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_seed_treatment_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_seed_treatment IS '种子处理记录表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_created_deleted ON bre_seed_treatment (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_bre_personnel_id ON bre_seed_treatment (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_combination ON bre_seed_treatment (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_combination_id ON bre_seed_treatment (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_created_id ON bre_seed_treatment (created_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_created_time ON bre_seed_treatment (created_time); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_deleted_id ON bre_seed_treatment (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_id ON bre_seed_treatment (id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_is_deleted ON bre_seed_treatment (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_personnel ON bre_seed_treatment (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_treatment_updated_id ON bre_seed_treatment (updated_id); -- ============================================================ -- 模块8: 杂种苗培育 -- ============================================================ -- 表: bre_seedling (杂种苗) -- 设计说明: 播种育苗记录,溯源到杂交组合;可被定植批次引用。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、personnel(bre_personnel_id 育苗人) -- * 下游: 被 planting(seedling_id) 引用 -- 字典来源字段: 无 -- 逻辑关系: 删除组合/育苗人 → 级联删除本记录;删除育苗 → 级联删除引用它的定植记录 CREATE TABLE IF NOT EXISTS bre_seedling ( combination_id int NOT NULL -- 所属组合, sowing_date varchar(20) -- 播移日期, tray_no varchar(100) -- 穴盘号, nursery varchar(100) -- 苗圃, seedling_count int -- 出苗数, remark text -- 备注, bre_personnel_id int -- 育苗人, treatment_id int, batch_no varchar(50), emergence_date varchar(20), strong_seedling_date varchar(20), strong_seedling_count int, stage varchar(1) DEFAULT '1'::character varying, CONSTRAINT fk_bre_seedling_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_seedling_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_seedling_treatment_id FOREIGN KEY (treatment_id) REFERENCES bre_seed_treatment (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_seedling_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_seedling IS '杂种苗培育记录表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_seedling_created_deleted ON bre_seedling (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_seedling_batch_no ON bre_seedling (batch_no); CREATE INDEX IF NOT EXISTS ix_bre_seedling_bre_personnel_id ON bre_seedling (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_combination ON bre_seedling (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_combination_id ON bre_seedling (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_created_id ON bre_seedling (created_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_created_time ON bre_seedling (created_time); CREATE INDEX IF NOT EXISTS ix_bre_seedling_deleted_id ON bre_seedling (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_id ON bre_seedling (id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_is_deleted ON bre_seedling (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_seedling_personnel ON bre_seedling (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_treatment_id ON bre_seedling (treatment_id); CREATE INDEX IF NOT EXISTS ix_bre_seedling_updated_id ON bre_seedling (updated_id); -- ============================================================ -- 模块9: 田间定植 -- ============================================================ -- 表: bre_planting (田间定植) -- 设计说明: 田间定植记录,关联组合/地块/育苗批次/定植人; -- 与 bre_tree 无硬外键(1 定植 → N 株,靠 combination_id+plot_id 关联,有意设计)。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、plot(plot_id)、 -- personnel(bre_personnel_id 定植人)、seedling(seedling_id 育苗批次) -- * 下游: 无 -- 字典来源字段: 无 -- 逻辑关系: 删除任一上游 → 级联删除本记录;定植批次可经 seedling_id 溯源到育苗批次 CREATE TABLE IF NOT EXISTS bre_planting ( combination_id int NOT NULL -- 所属组合, plot_id int -- 试验地块, planting_date varchar(20) -- 定植日期, tree_count int -- 定植株数, row_no int -- 行号, col_no int -- 列号, remark text -- 备注, seedling_id int -- 育苗批次, bre_personnel_id int -- 定植人, CONSTRAINT fk_bre_planting_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_planting_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_planting_plot_id FOREIGN KEY (plot_id) REFERENCES bre_plot (id), CONSTRAINT fk_bre_planting_seedling_id FOREIGN KEY (seedling_id) REFERENCES bre_seedling (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_planting_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_planting IS '田间定植记录表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_planting_created_deleted ON bre_planting (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_planting_bre_personnel_id ON bre_planting (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_combination ON bre_planting (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_combination_id ON bre_planting (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_created_id ON bre_planting (created_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_created_time ON bre_planting (created_time); CREATE INDEX IF NOT EXISTS ix_bre_planting_deleted_id ON bre_planting (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_id ON bre_planting (id); CREATE INDEX IF NOT EXISTS ix_bre_planting_is_deleted ON bre_planting (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_planting_personnel ON bre_planting (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_plot ON bre_planting (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_plot_id ON bre_planting (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_seedling ON bre_planting (seedling_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_seedling_id ON bre_planting (seedling_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_updated_id ON bre_planting (updated_id); -- ============================================================ -- 模块10: 育种单株(新增实体) -- ============================================================ -- 表: bre_tree (育种单株) -- 设计说明: 独立单株实体(新增),单株编号全局唯一;下游评价/照片/选育均经 -- tree_id 关联本表。修复原"tree_no 自由文本无统一实体"的断点。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、plot(plot_id) -- * 下游: 被 tree_evaluation(tree_id)/tree_photo(tree_id)/selection_result(tree_id) 引用 -- 字典来源字段: status(状态:存活/淘汰/入选) [字典],见 bre_dict.sql -- 逻辑关系: 删除单株 → 级联删除下游三表(评价/照片/选育) CREATE TABLE IF NOT EXISTS bre_tree ( combination_id int NOT NULL -- 所属组合, dam_id int -- 母本(种质), sire_id int -- 父本(种质), plot_id int -- 试验地块, tree_no varchar(100) NOT NULL -- 单株编号(全局唯一), row_no int -- 行号, col_no int -- 列号, planted_date varchar(20) -- 定植日期, status varchar(50) -- 状态(存活/淘汰/入选) [字典: tree_status], remark text -- 备注, row_orientation varchar(50), bre_personnel_id int, planting_id int, CONSTRAINT fk_bre_tree_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_tree_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_tree_dam_id FOREIGN KEY (dam_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_tree_sire_id FOREIGN KEY (sire_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_tree_planting_id FOREIGN KEY (planting_id) REFERENCES bre_planting (id), CONSTRAINT fk_bre_tree_plot_id FOREIGN KEY (plot_id) REFERENCES bre_plot (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_tree_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_tree IS '育种单株表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_tree_created_deleted ON bre_tree (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uniq_bre_tree_no ON bre_tree (tree_no) WHERE (is_deleted = false); CREATE INDEX IF NOT EXISTS ix_bre_tree_combination ON bre_tree (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_combination_id ON bre_tree (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_created_id ON bre_tree (created_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_created_time ON bre_tree (created_time); CREATE INDEX IF NOT EXISTS ix_bre_tree_deleted_id ON bre_tree (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_id ON bre_tree (id); CREATE INDEX IF NOT EXISTS ix_bre_tree_is_deleted ON bre_tree (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_tree_personnel ON bre_tree (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_planting_id ON bre_tree (planting_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_plot ON bre_tree (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_plot_id ON bre_tree (plot_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_updated_id ON bre_tree (updated_id); -- ============================================================ -- 模块11: 单株评价(果实性状内联,无独立 fruit_trait 表) -- ============================================================ -- 表: bre_tree_evaluation (单株评价) -- 设计说明: 单株年度评价主表;果实性状(果形/单果重/含糖量等)内联本表, -- 不单独建 breeding_fruit_trait 子表(与原规划不同)。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、tree(tree_id)、personnel(bre_personnel_id 评价人) -- * 下游: 无 -- 字典来源字段: growth_vigor(生长势:强/中/弱) [字典: growth_vigor], -- fruit_shape(果形:圆/扁圆/椭圆) [字典: fruit_shape],见 bre_dict.sql -- (fruit_weight/sugar_content 为数值字段,非字典) -- 逻辑关系: 删除组合/单株/评价人 → 级联删除本记录(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_tree_evaluation ( combination_id int NOT NULL -- 所属组合, evaluate_year int -- 评价年份(多年), evaluate_date varchar(20) -- 评价日期, remark text -- 备注, tree_id int NOT NULL -- 关联单株, bre_personnel_id int -- 评价人, overall_score float, CONSTRAINT fk_bre_tree_evaluation_bre_personnel_id FOREIGN KEY (bre_personnel_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_tree_evaluation_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_tree_evaluation_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_tree_evaluation_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_tree_evaluation IS '单株评价表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_created_deleted ON bre_tree_evaluation (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_bre_personnel_id ON bre_tree_evaluation (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_combination ON bre_tree_evaluation (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_combination_id ON bre_tree_evaluation (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_created_id ON bre_tree_evaluation (created_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_created_time ON bre_tree_evaluation (created_time); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_deleted_id ON bre_tree_evaluation (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_id ON bre_tree_evaluation (id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_is_deleted ON bre_tree_evaluation (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_personnel ON bre_tree_evaluation (bre_personnel_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_tree ON bre_tree_evaluation (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_tree_id ON bre_tree_evaluation (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_evaluation_updated_id ON bre_tree_evaluation (updated_id); -- ============================================================ -- 模块12: 单株照片 -- ============================================================ -- 表: bre_tree_photo (单株照片) -- 设计说明: 单株照片记录,关联组合与单株。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、tree(tree_id) -- * 下游: 无 -- 字典来源字段: photo_type(照片类型:全株/果实/枝干) [字典],见 bre_dict.sql -- 逻辑关系: 删除组合/单株 → 级联删除本记录(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_tree_photo ( combination_id int NOT NULL -- 所属组合, photo_type varchar(50) -- 照片类型(全株/果实/枝干) [字典: photo_type], photo_url varchar(100) -- 照片路径/URL, capture_date varchar(20) -- 拍摄日期, remark text -- 备注, tree_id int -- 关联单株, evaluation_id int, category varchar(50), CONSTRAINT fk_bre_tree_photo_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_tree_photo_evaluation_id FOREIGN KEY (evaluation_id) REFERENCES bre_tree_evaluation (id), CONSTRAINT fk_bre_tree_photo_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_tree_photo_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_tree_photo IS '单株照片表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_created_deleted ON bre_tree_photo (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_combination ON bre_tree_photo (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_combination_id ON bre_tree_photo (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_created_id ON bre_tree_photo (created_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_created_time ON bre_tree_photo (created_time); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_deleted_id ON bre_tree_photo (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_evaluation ON bre_tree_photo (evaluation_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_id ON bre_tree_photo (id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_is_deleted ON bre_tree_photo (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_tree ON bre_tree_photo (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_tree_id ON bre_tree_photo (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_tree_photo_updated_id ON bre_tree_photo (updated_id); -- ============================================================ -- 模块13: 选育结果(评价筛选) -- ============================================================ -- 表: bre_selection_result (选育结果) -- 设计说明: 单株选育结论(入选/淘汰/待定),关联组合与单株。 -- 与其它表关系: -- * 上游: 引用 cross_combination(combination_id)、tree(tree_id) -- * 下游: 无 -- 字典来源字段: is_selected(选育结论:入选/淘汰/待定) [字典],见 bre_dict.sql -- 逻辑关系: 删除组合/单株 → 级联删除本记录(外键均 CASCADE) CREATE TABLE IF NOT EXISTS bre_selection_result ( combination_id int NOT NULL -- 所属组合, tree_no varchar(100) NOT NULL, selection_year int -- 入选年份, is_selected varchar(50) -- 选育结论(入选/淘汰/待定) [字典: selection_result], reason text -- 入选理由, remark text -- 备注, tree_id int NOT NULL -- 关联单株, CONSTRAINT fk_bre_selection_result_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_selection_result_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_selection_result_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_selection_result IS '选育结果表(桃育种)'; CREATE INDEX IF NOT EXISTS ix_bre_selection_result_created_deleted ON bre_selection_result (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_combination ON bre_selection_result (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_combination_id ON bre_selection_result (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_created_id ON bre_selection_result (created_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_created_time ON bre_selection_result (created_time); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_deleted_id ON bre_selection_result (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_id ON bre_selection_result (id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_is_deleted ON bre_selection_result (is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_tree ON bre_selection_result (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_tree_id ON bre_selection_result (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_result_updated_id ON bre_selection_result (updated_id); -- ============================================================================ -- 规划新增模块(依据 桃育种系统模块扩展需求规格 v1.9 §3,2026-07-29 刷新) -- 说明:以下表尚未实装 model,待生成器落地后由 create_all / 迁移脚本建表。 -- 风格与上方 14 域一致:snake_case 表名 + 审计字段 + 外键 + (created_time, is_deleted) 索引。 -- ============================================================================ -- §3.1 性状字典(核心性状 is_core=true 固定列,扩展性状 EAV) CREATE TABLE IF NOT EXISTS bre_trait ( trait_code varchar(64) NOT NULL, trait_name varchar(128) NOT NULL, category varchar(32), data_type varchar(16) NOT NULL DEFAULT 'numeric'::character varying, unit varchar(16), is_core varchar(1) NOT NULL DEFAULT '1'::character varying, scale_json text, valid_min numeric(12,3), valid_max numeric(12,3), ontology_uri varchar(255), remark varchar(512), CONSTRAINT uq_bre_trait_code UNIQUE (trait_code), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_trait_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_trait IS '性状字典(§3.1);核心性状固定列承载表型,is_core=false 走 observation EAV'; CREATE INDEX IF NOT EXISTS ix_bre_trait_created_deleted ON bre_trait (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_trait_created_id ON bre_trait (created_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_deleted_id ON bre_trait (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_updated_id ON bre_trait (updated_id); -- §3.2 扩展观测(EAV,物候时序 + 非核心性状) CREATE TABLE IF NOT EXISTS bre_observation ( tree_id int, plot_id int, trait_id int, obs_date date, obs_year int, obs_value text, obs_type varchar(32), trial_study_id int, operator_id int, remark varchar(512), status int NOT NULL DEFAULT 1, CONSTRAINT fk_bre_observation_trait_id FOREIGN KEY (trait_id) REFERENCES bre_trait (id), CONSTRAINT fk_bre_observation_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id bigserial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_observation_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_observation IS '扩展观测 EAV(§3.2);与 tree_evaluation 经统一性状值视图归一'; CREATE INDEX IF NOT EXISTS ix_bre_observation_created_deleted ON bre_observation (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_observation_created_id ON bre_observation (created_id); CREATE INDEX IF NOT EXISTS ix_bre_observation_deleted_id ON bre_observation (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_observation_updated_id ON bre_observation (updated_id); -- §3.3 农事操作 CREATE TABLE IF NOT EXISTS bre_field_operation ( tree_id int, plot_id int, op_type varchar(32) NOT NULL, op_date date, op_detail text, operator_id int, remark varchar(512), status int NOT NULL DEFAULT 1, CONSTRAINT fk_bre_field_operation_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id bigserial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_field_operation_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_field_operation IS '农事操作(§3.3)'; CREATE INDEX IF NOT EXISTS ix_bre_field_operation_created_deleted ON bre_field_operation (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_field_operation_created_id ON bre_field_operation (created_id); CREATE INDEX IF NOT EXISTS ix_bre_field_operation_deleted_id ON bre_field_operation (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_field_operation_updated_id ON bre_field_operation (updated_id); -- §3.4 MET 试验结构:试验 / 研究 / 参试项 CREATE TABLE IF NOT EXISTS bre_trial ( trial_name varchar(128) NOT NULL, trial_type varchar(32), design_type varchar(32), start_year int, end_year int, objective varchar(512), remark varchar(512), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_trial_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_trial IS 'MET 试验(§3.4)'; CREATE INDEX IF NOT EXISTS ix_bre_trial_created_id ON bre_trial (created_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_deleted_id ON bre_trial (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_updated_id ON bre_trial (updated_id); CREATE TABLE IF NOT EXISTS bre_trial_study ( trial_id int NOT NULL, study_name varchar(128) NOT NULL, site_id int, year int, block_count int, design_type varchar(32), remark varchar(512), CONSTRAINT fk_bre_trial_study_site_id FOREIGN KEY (site_id) REFERENCES bre_site (id), CONSTRAINT fk_bre_trial_study_trial_id FOREIGN KEY (trial_id) REFERENCES bre_trial (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_trial_study_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_trial_study IS 'MET 研究(多年点,block 随机效应来源)'; CREATE INDEX IF NOT EXISTS ix_bre_trial_study_created_id ON bre_trial_study (created_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_study_deleted_id ON bre_trial_study (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_study_updated_id ON bre_trial_study (updated_id); CREATE TABLE IF NOT EXISTS bre_trial_study_entry ( trial_study_id int NOT NULL, entry_number int NOT NULL, germplasm_id int NOT NULL, combination_id int, remark varchar(512), CONSTRAINT fk_bre_trial_study_entry_germplasm_id FOREIGN KEY (germplasm_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_trial_study_entry_trial_study_id FOREIGN KEY (trial_study_id) REFERENCES bre_trial_study (id), CONSTRAINT bre_trial_study_entry_uuid_key UNIQUE (uuid), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_trial_study_entry_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_trial_study_entry IS '参试项(design matrix 聚合键 entry_number)'; CREATE INDEX IF NOT EXISTS ix_bre_trial_study_entry_created_deleted ON bre_trial_study_entry (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_trial_study_entry_created_id ON bre_trial_study_entry (created_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_study_entry_deleted_id ON bre_trial_study_entry (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_trial_study_entry_updated_id ON bre_trial_study_entry (updated_id); -- §3.5 分组/标签(family 虚拟 + category 复用) CREATE TABLE IF NOT EXISTS bre_group ( group_name varchar(128) NOT NULL, group_type varchar(32), remark varchar(512), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_group_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_group IS '分组/标签(§3.5;family 虚拟组/category 复用)'; CREATE INDEX IF NOT EXISTS ix_bre_group_created_id ON bre_group (created_id); CREATE INDEX IF NOT EXISTS ix_bre_group_deleted_id ON bre_group (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_group_updated_id ON bre_group (updated_id); CREATE TABLE IF NOT EXISTS bre_group_member ( group_id int, member_type varchar(16), member_id int, CONSTRAINT fk_bre_group_member_group_id FOREIGN KEY (group_id) REFERENCES bre_group (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_group_member_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_group_member_created_id ON bre_group_member (created_id); CREATE INDEX IF NOT EXISTS ix_bre_group_member_deleted_id ON bre_group_member (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_group_member_updated_id ON bre_group_member (updated_id); -- §3.6 育种报告(v1.7 进一期) CREATE TABLE IF NOT EXISTS bre_report ( report_name varchar(128) NOT NULL, report_type varchar(32), year int, target_id int, doc_path varchar(512), gen_by varchar(64), remark varchar(512), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_report_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_report IS '育种报告(§3.6,docx/pdf 导出,v1.7 进一期)'; CREATE INDEX IF NOT EXISTS ix_bre_report_created_id ON bre_report (created_id); CREATE INDEX IF NOT EXISTS ix_bre_report_deleted_id ON bre_report (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_report_updated_id ON bre_report (updated_id); -- §3.7 分子基因型层(V2.0) CREATE TABLE IF NOT EXISTS bre_marker ( marker_name varchar(64) NOT NULL, chromosome varchar(16), position int, marker_type varchar(16), panel varchar(32), assembly_version varchar(32), remark varchar(512), CONSTRAINT uq_bre_marker_name UNIQUE (marker_name), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_marker_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_marker IS '分子标记(§3.7;SSR/SNP,panel/assembly_version 供 GS 同版本)'; CREATE INDEX IF NOT EXISTS ix_bre_marker_created_id ON bre_marker (created_id); CREATE INDEX IF NOT EXISTS ix_bre_marker_deleted_id ON bre_marker (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_marker_updated_id ON bre_marker (updated_id); CREATE TABLE IF NOT EXISTS bre_genotyping_dataset ( dataset_name varchar(128) NOT NULL, platform varchar(32), panel varchar(32), purpose varchar(16), run_date date, lab varchar(128), remark varchar(512), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_genotyping_dataset_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_genotyping_dataset_created_id ON bre_genotyping_dataset (created_id); CREATE INDEX IF NOT EXISTS ix_bre_genotyping_dataset_deleted_id ON bre_genotyping_dataset (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_genotyping_dataset_updated_id ON bre_genotyping_dataset (updated_id); CREATE TABLE IF NOT EXISTS bre_genotype_sample ( dataset_id int, source_type varchar(16), source_id int, sample_type varchar(16), sample_date date, method varchar(64), lab varchar(128), remark varchar(512), CONSTRAINT fk_bre_genotype_sample_dataset_id FOREIGN KEY (dataset_id) REFERENCES bre_genotyping_dataset (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_genotype_sample_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_genotype_sample_created_id ON bre_genotype_sample (created_id); CREATE INDEX IF NOT EXISTS ix_bre_genotype_sample_deleted_id ON bre_genotype_sample (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_genotype_sample_updated_id ON bre_genotype_sample (updated_id); CREATE TABLE IF NOT EXISTS bre_genotype_call ( sample_id int, marker_id int, allele varchar(32), remark varchar(256), CONSTRAINT fk_bre_genotype_call_marker_id FOREIGN KEY (marker_id) REFERENCES bre_marker (id), CONSTRAINT fk_bre_genotype_call_sample_id FOREIGN KEY (sample_id) REFERENCES bre_genotype_sample (id), CONSTRAINT uq_genotype_call_sample_marker UNIQUE (sample_id, marker_id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_genotype_call_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_genotype_call IS '基因型调用(§3.7;allele 遵循 VCF/GP 0/1/2 编码)'; CREATE INDEX IF NOT EXISTS ix_bre_genotype_call_created_id ON bre_genotype_call (created_id); CREATE INDEX IF NOT EXISTS ix_bre_genotype_call_deleted_id ON bre_genotype_call (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_genotype_call_updated_id ON bre_genotype_call (updated_id); -- §3.8 克隆扩繁(P1,一期) CREATE TABLE IF NOT EXISTS bre_propagation ( batch_code varchar(64) NOT NULL, scion_source_type varchar(16), scion_source_id int, produced_germplasm_id int, rootstock_id int, method varchar(16), graft_date date, nursery_site_id int, operator_id int, scion_count int, grafted_count int, survival_count int, destination varchar(32), remark varchar(512), CONSTRAINT fk_bre_propagation_nursery_site_id FOREIGN KEY (nursery_site_id) REFERENCES bre_site (id), CONSTRAINT fk_bre_propagation_operator_id FOREIGN KEY (operator_id) REFERENCES bre_personnel (id), CONSTRAINT fk_bre_propagation_produced_germplasm_id FOREIGN KEY (produced_germplasm_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_propagation_rootstock_id FOREIGN KEY (rootstock_id) REFERENCES bre_germplasm (id), CONSTRAINT uq_bre_propagation_batch UNIQUE (batch_code), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_propagation_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_propagation IS '克隆扩繁批次(§3.8;入选株→克隆种质→扩繁→新树闭环)'; CREATE INDEX IF NOT EXISTS ix_bre_propagation_created_id ON bre_propagation (created_id); CREATE INDEX IF NOT EXISTS ix_bre_propagation_deleted_id ON bre_propagation (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_propagation_updated_id ON bre_propagation (updated_id); -- §3.9 环境因子(G×E 协变量) CREATE TABLE IF NOT EXISTS bre_environment_condition ( site_id int, year int, chilling_hours numeric(8,1), growing_degree_days numeric(8,1), rainfall_mm numeric(8,1), temp_avg numeric(6,1), soil_moisture numeric(6,1), source varchar(32), remark varchar(512), CONSTRAINT fk_bre_environment_condition_site_id FOREIGN KEY (site_id) REFERENCES bre_site (id), CONSTRAINT uq_env_site_year UNIQUE (site_id, year), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_environment_condition_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_environment_condition IS '环境因子(§3.9;G×E 协变量,site×year 唯一)'; CREATE INDEX IF NOT EXISTS ix_bre_environment_condition_created_id ON bre_environment_condition (created_id); CREATE INDEX IF NOT EXISTS ix_bre_environment_condition_deleted_id ON bre_environment_condition (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_environment_condition_updated_id ON bre_environment_condition (updated_id); -- §3.10 审计切面(通用,Service 写操作落) CREATE TABLE IF NOT EXISTS bre_audit_log ( entity_type varchar(32), entity_id int, action varchar(32), field_name varchar(64), old_value varchar(512), new_value varchar(512), operator_id int, CONSTRAINT fk_bre_audit_log_operator_id FOREIGN KEY (operator_id) REFERENCES bre_personnel (id), id bigserial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_audit_log_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_audit_log IS '审计日志(§3.10;晋级审批/全程可追溯切面)'; CREATE INDEX IF NOT EXISTS ix_bre_audit_created ON bre_audit_log (created_time); CREATE INDEX IF NOT EXISTS ix_bre_audit_entity ON bre_audit_log (entity_type, entity_id); CREATE INDEX IF NOT EXISTS ix_bre_audit_log_created_id ON bre_audit_log (created_id); CREATE INDEX IF NOT EXISTS ix_bre_audit_log_deleted_id ON bre_audit_log (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_audit_log_updated_id ON bre_audit_log (updated_id); -- §3.11 选择规则(阈值/指数条件) CREATE TABLE IF NOT EXISTS bre_selection_rule ( rule_name varchar(128) NOT NULL, target_id int NOT NULL, stage varchar(32), conditions_json text NOT NULL, logic varchar(8) DEFAULT 'and'::character varying, action varchar(16), priority int, enabled varchar(1) DEFAULT '1'::character varying, remark varchar(512), CONSTRAINT fk_bre_selection_rule_target_id FOREIGN KEY (target_id) REFERENCES bre_target (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_selection_rule_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_selection_rule IS '选择规则(§3.11;conditions_json 阈值,可引用 trait_code/EBV)'; CREATE INDEX IF NOT EXISTS ix_bre_selection_rule_created_id ON bre_selection_rule (created_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_rule_deleted_id ON bre_selection_rule (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_selection_rule_updated_id ON bre_selection_rule (updated_id); -- §3.12 育种值:模型元数据 + 值表(值表 V1.1 前移) CREATE TABLE IF NOT EXISTS bre_prediction ( model_name varchar(128), trait_id int, method varchar(32), accuracy numeric(5,3), train_n int, heritability numeric(5,4), predict_date date, note varchar(512), CONSTRAINT fk_bre_prediction_trait_id FOREIGN KEY (trait_id) REFERENCES bre_trait (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_prediction_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_prediction IS '育种值模型/批次元数据(§3.12)'; CREATE INDEX IF NOT EXISTS ix_bre_prediction_created_deleted ON bre_prediction (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_prediction_created_id ON bre_prediction (created_id); CREATE INDEX IF NOT EXISTS ix_bre_prediction_deleted_id ON bre_prediction (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_prediction_updated_id ON bre_prediction (updated_id); CREATE TABLE IF NOT EXISTS bre_prediction_value ( prediction_id int NOT NULL, germplasm_id int, tree_id int, trait_id int, predicted_value numeric(12,4), reliability numeric(6,4), rank int, CONSTRAINT fk_bre_prediction_value_germplasm_id FOREIGN KEY (germplasm_id) REFERENCES bre_germplasm (id), CONSTRAINT fk_bre_prediction_value_prediction_id FOREIGN KEY (prediction_id) REFERENCES bre_prediction (id), CONSTRAINT fk_bre_prediction_value_trait_id FOREIGN KEY (trait_id) REFERENCES bre_trait (id), id bigserial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_prediction_value_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_prediction_value IS '个体预测值(EBV 持久化,V1.1 建表;趋势图/双轨选择/亲本决策读)'; CREATE INDEX IF NOT EXISTS ix_bre_prediction_value_created_deleted ON bre_prediction_value (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_prediction_value_created_id ON bre_prediction_value (created_id); CREATE INDEX IF NOT EXISTS ix_bre_prediction_value_deleted_id ON bre_prediction_value (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_prediction_value_updated_id ON bre_prediction_value (updated_id); -- §3.12 补充:配合力分析结果(GCA/SCA 持久化,一期落地) CREATE TABLE IF NOT EXISTS bre_combining_ability ( model_name varchar(128), trait_id int, method varchar(16), gca_json jsonb, sca_json jsonb, CONSTRAINT fk_bre_combining_ability_trait_id FOREIGN KEY (trait_id) REFERENCES bre_trait (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_combining_ability_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_combining_ability IS '配合力分析结果(§3.12;GCA 按亲本、SCA 按组合,一期落地)'; CREATE INDEX IF NOT EXISTS ix_bre_combining_ability_created_deleted ON bre_combining_ability (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_combining_ability_created_id ON bre_combining_ability (created_id); CREATE INDEX IF NOT EXISTS ix_bre_combining_ability_deleted_id ON bre_combining_ability (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_combining_ability_updated_id ON bre_combining_ability (updated_id); -- §5 统计异步任务(R 引擎异步 job 队列) CREATE TABLE IF NOT EXISTS bre_statistics_job ( job_type varchar(32), params_json jsonb, status varchar(16) NOT NULL DEFAULT 'PENDING'::character varying, result_ref int, error_msg text, started_time timestamptz, finished_time timestamptz, id bigserial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_statistics_job_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_statistics_job IS '统计异步任务(R 引擎;ABLUP/COMBINING 提交后异步执行并回写结果)'; CREATE INDEX IF NOT EXISTS ix_bre_statistics_job_created_deleted ON bre_statistics_job (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_statistics_job_created_id ON bre_statistics_job (created_id); CREATE INDEX IF NOT EXISTS ix_bre_statistics_job_deleted_id ON bre_statistics_job (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_statistics_job_updated_id ON bre_statistics_job (updated_id); -- §3.13 种子批(选择强度链前段) CREATE TABLE IF NOT EXISTS bre_seed_lot ( combination_id int, lot_code varchar(64) NOT NULL, harvest_year int, seed_count int, used_count int DEFAULT 0, germination_rate numeric(5,2), storage_type varchar(16), storage_location varchar(128), test_date date, remark varchar(512), CONSTRAINT fk_bre_seed_lot_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT uq_bre_seed_lot_code UNIQUE (lot_code), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_seed_lot_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_seed_lot IS '种子批(§3.13;used_count 派生 remaining,选择强度链源头)'; CREATE INDEX IF NOT EXISTS ix_bre_seed_lot_created_id ON bre_seed_lot (created_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_lot_deleted_id ON bre_seed_lot (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_seed_lot_updated_id ON bre_seed_lot (updated_id); -- §3.14 试验处理(裂区/析因 factor×level) CREATE TABLE IF NOT EXISTS bre_treatment ( trial_study_id int NOT NULL, factor varchar(32) NOT NULL, level varchar(32) NOT NULL, description varchar(256), remark varchar(512), CONSTRAINT fk_bre_treatment_trial_study_id FOREIGN KEY (trial_study_id) REFERENCES bre_trial_study (id), CONSTRAINT uq_treatment_factor_level UNIQUE (trial_study_id, factor, level), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_treatment_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_treatment IS '试验处理(§3.14;factor×level,BrAPI Treatment/MIAPPE ExperimentalFactor)'; CREATE INDEX IF NOT EXISTS ix_bre_treatment_created_id ON bre_treatment (created_id); CREATE INDEX IF NOT EXISTS ix_bre_treatment_deleted_id ON bre_treatment (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_treatment_updated_id ON bre_treatment (updated_id); -- §3.15 定植-处理关联(多对多) CREATE TABLE IF NOT EXISTS bre_planting_treatment ( planting_id int, treatment_id int, remark varchar(512), CONSTRAINT fk_bre_planting_treatment_planting_id FOREIGN KEY (planting_id) REFERENCES bre_planting (id), CONSTRAINT fk_bre_planting_treatment_treatment_id FOREIGN KEY (treatment_id) REFERENCES bre_treatment (id), CONSTRAINT uq_planting_treatment UNIQUE (planting_id, treatment_id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_planting_treatment_uuid UNIQUE (uuid) ); COMMENT ON TABLE bre_planting_treatment IS '定植-处理关联(§3.15;因子效应挂到 block 级批次全部 tree)'; CREATE INDEX IF NOT EXISTS ix_bre_planting_treatment_created_id ON bre_planting_treatment (created_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_treatment_deleted_id ON bre_planting_treatment (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_planting_treatment_updated_id ON bre_planting_treatment (updated_id); -- §3.x 系谱管理(v1.9 补充;基于杂交组合自链 + 种质系谱串派生,独立维护亲子/世代关系) CREATE TABLE IF NOT EXISTS bre_pedigree ( combination_id int NOT NULL, child_code varchar(64) NOT NULL, generation varchar(16), remark varchar(512), CONSTRAINT fk_bre_pedigree_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_pedigree_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_pedigree_created_deleted ON bre_pedigree (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_pedigree_created_id ON bre_pedigree (created_id); CREATE INDEX IF NOT EXISTS ix_bre_pedigree_deleted_id ON bre_pedigree (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_pedigree_updated_id ON bre_pedigree (updated_id); -- §3.x 育种计划(v1.9 补充;顶层计划,germplasm.breeding_program 后续可升级为指向本表 FK) CREATE TABLE IF NOT EXISTS bre_plan ( plan_code varchar(64) NOT NULL, plan_name varchar(128) NOT NULL, objective varchar(512), start_year int, end_year int, leader varchar(64), remark varchar(512), CONSTRAINT uq_bre_plan_code UNIQUE (plan_code), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_plan_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_plan_created_deleted ON bre_plan (created_time, is_deleted); CREATE INDEX IF NOT EXISTS ix_bre_plan_created_id ON bre_plan (created_id); CREATE INDEX IF NOT EXISTS ix_bre_plan_deleted_id ON bre_plan (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_plan_updated_id ON bre_plan (updated_id); -- ===================================================================== -- 结构对齐补丁(V1.9 表 -> ModelMixin 基类契约) -- 幂等,可重复执行:补齐 uuid / deleted_time,并将 is_deleted integer 改为 boolean。 -- 背景:v1.9 规格建表时遗漏 uuid/deleted_time 且 is_deleted 用 int, -- 而 _gen_specs 生成器产出的 model 继承 ModelMixin(要求这 3 列)。 -- ===================================================================== CREATE EXTENSION IF NOT EXISTS pgcrypto; DO $$ DECLARE t text; BEGIN FOREACH t IN ARRAY ARRAY[ 'bre_trait','bre_selection_rule','bre_trial', 'bre_trial_study','bre_treatment','bre_group', 'bre_pedigree','bre_plan' ] LOOP -- uuid(唯一) IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = t AND column_name = 'uuid' ) THEN EXECUTE format('ALTER TABLE %I ADD COLUMN uuid varchar(64) NOT NULL DEFAULT gen_random_uuid()', t); EXECUTE format('CREATE UNIQUE INDEX IF NOT EXISTS uq_%I_uuid ON %I(uuid)', t, t); END IF; -- deleted_time(软删除时间,可空) IF NOT EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = t AND column_name = 'deleted_time' ) THEN EXECUTE format('ALTER TABLE %I ADD COLUMN deleted_time timestamptz', t); END IF; -- is_deleted: integer -> boolean IF EXISTS ( SELECT 1 FROM information_schema.columns WHERE table_name = t AND column_name = 'is_deleted' AND data_type = 'integer' ) THEN EXECUTE format('ALTER TABLE %I ALTER COLUMN is_deleted DROP DEFAULT', t); EXECUTE format('ALTER TABLE %I ALTER COLUMN is_deleted TYPE boolean USING (is_deleted = 1)', t); EXECUTE format('ALTER TABLE %I ALTER COLUMN is_deleted SET DEFAULT false', t); END IF; END LOOP; END $$; -- ============================================================ -- 模块: 单株鉴定(性状观测明细长表 EAV,evaluation_upgrade 新增) -- ============================================================ -- 表: bre_trait_observation (性状观测明细) -- 设计说明: 单株鉴定性状值长表(EAV)。 -- 与其它表关系: tree / tree_evaluation / trait / cross_combination 外键。 -- 约束: 同一次鉴定内同一性状仅一条(evaluation_id 非空时)。 CREATE TABLE IF NOT EXISTS bre_trait_observation ( evaluation_id int, tree_id int, combination_id int, trait_id int NOT NULL, evaluate_year int, value_numeric float, value_text varchar(255), value_date varchar(20), remark text, CONSTRAINT fk_bre_trait_observation_combination_id FOREIGN KEY (combination_id) REFERENCES bre_cross_combination (id), CONSTRAINT fk_bre_trait_observation_evaluation_id FOREIGN KEY (evaluation_id) REFERENCES bre_tree_evaluation (id), CONSTRAINT fk_bre_trait_observation_trait_id FOREIGN KEY (trait_id) REFERENCES bre_trait (id), CONSTRAINT fk_bre_trait_observation_tree_id FOREIGN KEY (tree_id) REFERENCES bre_tree (id), id serial PRIMARY KEY, uuid varchar(64) NOT NULL UNIQUE, is_deleted boolean NOT NULL DEFAULT false, created_time timestamptz NOT NULL DEFAULT now(), updated_time timestamptz NOT NULL DEFAULT now(), deleted_time timestamptz, created_id integer REFERENCES sys_user(id) ON DELETE SET NULL, updated_id integer REFERENCES sys_user(id) ON DELETE SET NULL, deleted_id integer REFERENCES sys_user(id) ON DELETE SET NULL, CONSTRAINT uq_bre_trait_observation_uuid UNIQUE (uuid) ); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_created_deleted ON bre_trait_observation (created_time, is_deleted); CREATE UNIQUE INDEX IF NOT EXISTS uq_bre_trait_observation_eval_trait ON bre_trait_observation (evaluation_id, trait_id) WHERE ((evaluation_id IS NOT NULL) AND (is_deleted = false)); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_combination ON bre_trait_observation (combination_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_created_id ON bre_trait_observation (created_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_deleted_id ON bre_trait_observation (deleted_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_evaluation ON bre_trait_observation (evaluation_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_trait ON bre_trait_observation (trait_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_tree ON bre_trait_observation (tree_id); CREATE INDEX IF NOT EXISTS ix_bre_trait_observation_updated_id ON bre_trait_observation (updated_id);