74 lines
3.4 KiB
Python
74 lines
3.4 KiB
Python
"""基地与试验地管理 —— 数据模型
|
||
|
||
两张无 `status` 列的域表,必须显式覆盖 `__table_args__`,
|
||
只保留 `created_time` / `is_deleted` 索引(框架基类默认会加
|
||
`ix_<表>_status` 索引,但本表无 status 列,不覆盖会建表失败)。
|
||
"""
|
||
from datetime import datetime
|
||
|
||
from sqlalchemy import Float, ForeignKey, Index, Integer, String, Text, text
|
||
from sqlalchemy.orm import Mapped, mapped_column
|
||
|
||
from app.core.base_model import MappedBase, ModelMixin, UserMixin
|
||
|
||
|
||
class BreedingSiteModel(ModelMixin, UserMixin, MappedBase):
|
||
"""育种基地(试验站)主数据表。"""
|
||
|
||
__tablename__ = "bre_site"
|
||
|
||
site_name: Mapped[str] = mapped_column(
|
||
String(100), nullable=False, unique=True, comment="基地名称"
|
||
)
|
||
address: Mapped[str | None] = mapped_column(String(255), nullable=True, comment="详细地址")
|
||
area: Mapped[float | None] = mapped_column(Float, nullable=True, comment="基地面积(亩)")
|
||
longitude: Mapped[float | None] = mapped_column(Float, nullable=True, comment="经度")
|
||
latitude: Mapped[float | None] = mapped_column(Float, nullable=True, comment="纬度")
|
||
eco_type: Mapped[str | None] = mapped_column(
|
||
String(50), nullable=True, comment="生态区类型(如 华北/西北/华东/西南/东北/华南)"
|
||
)
|
||
soil_type: Mapped[str | None] = mapped_column(String(50), nullable=True, comment="土壤类型", default=None)
|
||
elevation: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="海拔(m)", default=None)
|
||
remark: Mapped[str | None] = mapped_column(Text, nullable=True, comment="备注")
|
||
|
||
# 注:created_time / is_deleted 已由 ModelMixin 的 index=True 自动建索引
|
||
# (ix_bre_site_created_time / ix_bre_site_is_deleted),此处仅补一个
|
||
# 复合索引用于数据权限过滤,且必须覆盖基类默认会建的 ix_<表>_status_deleted
|
||
# (本表无 status 列,不覆盖会引用不存在的列而建表失败)。
|
||
__table_args__ = (
|
||
Index("ix_bre_site_created_deleted", "created_time", "is_deleted"),
|
||
)
|
||
|
||
|
||
class BreedingPlotModel(ModelMixin, UserMixin, MappedBase):
|
||
"""试验地块 —— 隶属于某个基地。"""
|
||
|
||
__tablename__ = "bre_plot"
|
||
|
||
site_id: Mapped[int] = mapped_column(
|
||
Integer,
|
||
ForeignKey("bre_site.id", ondelete="CASCADE"),
|
||
nullable=False,
|
||
index=True,
|
||
comment="所属基地ID",
|
||
)
|
||
plot_code: Mapped[str] = mapped_column(
|
||
String(50), nullable=False, comment="地块编号/名称"
|
||
)
|
||
row_orientation: Mapped[str | None] = mapped_column(
|
||
String(20), nullable=True, comment="行向(南北行/东西行)"
|
||
)
|
||
row_count: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="行数")
|
||
col_count: Mapped[int | None] = mapped_column(Integer, nullable=True, comment="每行株数")
|
||
grid_note: Mapped[str | None] = mapped_column(Text, nullable=True, comment="株行距/网格说明")
|
||
area: Mapped[float | None] = mapped_column(Float, nullable=True, comment="地块面积(亩)")
|
||
|
||
__table_args__ = (
|
||
Index("ix_bre_plot_created_deleted", "created_time", "is_deleted"),
|
||
# 基地内地块编号唯一(仅约束未软删记录,与 service 层查重语义一致)
|
||
Index(
|
||
"uniq_bre_plot_site_code", "site_id", "plot_code",
|
||
unique=True, postgresql_where=text("is_deleted = false"),
|
||
),
|
||
)
|