数据:增加测试批次模型与迁移契约
This commit is contained in:
@@ -28,3 +28,14 @@ class PalletEventType(str, Enum):
|
||||
USAGE_RECORDED = 'USAGE_RECORDED'
|
||||
RETURN_REQUESTED = 'RETURN_REQUESTED'
|
||||
RETURN_CONFIRMED = 'RETURN_CONFIRMED'
|
||||
|
||||
|
||||
class TestBatchStatus(str, Enum):
|
||||
ACTIVE = 'ACTIVE'
|
||||
CLOSED = 'CLOSED'
|
||||
PURGED = 'PURGED'
|
||||
|
||||
|
||||
class TestBatchPreviewAction(str, Enum):
|
||||
ADOPT = 'ADOPT'
|
||||
PURGE = 'PURGE'
|
||||
|
||||
@@ -27,6 +27,13 @@ class BizStrain(Base):
|
||||
)
|
||||
|
||||
strain_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='菌种ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
strain_code = Column(String(64), nullable=False, unique=True, comment='菌种编码')
|
||||
strain_name = Column(String(100), nullable=False, comment='菌种名称')
|
||||
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
|
||||
@@ -52,6 +59,13 @@ class BizWarehouse(Base):
|
||||
)
|
||||
|
||||
warehouse_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='仓库ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
warehouse_code = Column(String(64), nullable=False, unique=True, comment='仓库编码')
|
||||
warehouse_name = Column(String(100), nullable=False, comment='仓库名称')
|
||||
address = Column(String(500), nullable=True, comment='仓库地址')
|
||||
@@ -78,6 +92,13 @@ class BizCustomer(Base):
|
||||
)
|
||||
|
||||
customer_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='客户ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
customer_code = Column(String(64), nullable=False, unique=True, comment='客户编码')
|
||||
customer_name = Column(String(100), nullable=False, comment='客户名称')
|
||||
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
|
||||
@@ -104,6 +125,13 @@ class BizCustomerSite(Base):
|
||||
)
|
||||
|
||||
site_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='现场ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
customer_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_customer.customer_id'),
|
||||
@@ -137,6 +165,13 @@ class BizProductionLine(Base):
|
||||
)
|
||||
|
||||
line_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='产线ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
site_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_customer_site.site_id'),
|
||||
@@ -169,6 +204,13 @@ class BizPallet(Base):
|
||||
)
|
||||
|
||||
pallet_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='托盘ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
pallet_code = Column(String(64), nullable=False, unique=True, comment='托盘编号')
|
||||
qr_token = Column(String(128), nullable=False, unique=True, comment='二维码固定标识')
|
||||
capacity_packages = Column(Integer, nullable=False, comment='容量包数')
|
||||
|
||||
@@ -22,6 +22,13 @@ class BizInboundOrder(Base):
|
||||
)
|
||||
|
||||
inbound_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='入库单ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
inbound_no = Column(String(64), nullable=False, unique=True, comment='入库单号')
|
||||
warehouse_id = Column(
|
||||
BigInteger,
|
||||
@@ -62,6 +69,13 @@ class BizInboundItem(Base):
|
||||
autoincrement=True,
|
||||
comment='入库明细ID',
|
||||
)
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
inbound_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_inbound_order.inbound_id'),
|
||||
@@ -93,6 +107,13 @@ class BizFillingRecord(Base):
|
||||
)
|
||||
|
||||
filling_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='装填记录ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
filling_no = Column(String(64), nullable=False, unique=True, comment='装填单号')
|
||||
pallet_id = Column(BigInteger, ForeignKey('biz_pallet.pallet_id'), nullable=False, comment='托盘ID')
|
||||
warehouse_id = Column(
|
||||
@@ -141,6 +162,13 @@ class BizShipmentOrder(Base):
|
||||
)
|
||||
|
||||
shipment_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='发货单ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
shipment_no = Column(String(64), nullable=False, unique=True, comment='发货单号')
|
||||
source_warehouse_id = Column(
|
||||
BigInteger,
|
||||
@@ -191,6 +219,13 @@ class BizShipmentItem(Base):
|
||||
autoincrement=True,
|
||||
comment='发货明细ID',
|
||||
)
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
shipment_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_shipment_order.shipment_id'),
|
||||
@@ -224,6 +259,13 @@ class BizUsageRecord(Base):
|
||||
)
|
||||
|
||||
usage_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='使用记录ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
usage_no = Column(String(64), nullable=False, unique=True, comment='使用记录号')
|
||||
pallet_id = Column(BigInteger, ForeignKey('biz_pallet.pallet_id'), nullable=False, comment='托盘ID')
|
||||
active_filling_id = Column(
|
||||
@@ -264,6 +306,13 @@ class BizReturnOrder(Base):
|
||||
)
|
||||
|
||||
return_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='退回单ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
return_no = Column(String(64), nullable=False, unique=True, comment='退回单号')
|
||||
source_site_id = Column(
|
||||
BigInteger,
|
||||
@@ -318,6 +367,13 @@ class BizReturnItem(Base):
|
||||
autoincrement=True,
|
||||
comment='退回明细ID',
|
||||
)
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
return_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_return_order.return_id'),
|
||||
@@ -363,6 +419,13 @@ class BizPalletInventory(Base):
|
||||
autoincrement=False,
|
||||
comment='托盘ID',
|
||||
)
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
active_filling_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_filling_record.filling_id'),
|
||||
@@ -415,6 +478,13 @@ class BizPalletEvent(Base):
|
||||
)
|
||||
|
||||
event_id = Column(BigInteger, primary_key=True, nullable=False, autoincrement=True, comment='事件ID')
|
||||
test_batch_id = Column(
|
||||
BigInteger,
|
||||
ForeignKey('biz_test_batch.batch_id'),
|
||||
nullable=True,
|
||||
index=True,
|
||||
comment='测试数据批次ID;NULL表示正式数据',
|
||||
)
|
||||
pallet_id = Column(BigInteger, ForeignKey('biz_pallet.pallet_id'), nullable=False, comment='托盘ID')
|
||||
event_seq = Column(Integer, nullable=False, comment='托盘内事件序号')
|
||||
event_type = Column(String(32), nullable=False, comment='事件类型')
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from datetime import datetime
|
||||
|
||||
from sqlalchemy import CHAR, BigInteger, CheckConstraint, Column, DateTime, ForeignKey, String, Text
|
||||
|
||||
from config.database import Base
|
||||
|
||||
|
||||
class BizTestBatch(Base):
|
||||
"""测试数据批次。"""
|
||||
|
||||
__tablename__ = 'biz_test_batch'
|
||||
__table_args__ = (
|
||||
CheckConstraint("status IN ('ACTIVE', 'CLOSED', 'PURGED')", name='ck_biz_test_batch_status'),
|
||||
CheckConstraint(
|
||||
"preview_action IS NULL OR preview_action IN ('ADOPT', 'PURGE')",
|
||||
name='ck_biz_test_batch_preview_action',
|
||||
),
|
||||
{'comment': '测试数据批次'},
|
||||
)
|
||||
|
||||
batch_id = Column(BigInteger, primary_key=True, autoincrement=True)
|
||||
batch_code = Column(String(64), nullable=False, unique=True)
|
||||
batch_name = Column(String(100), nullable=False)
|
||||
status = Column(String(16), nullable=False, server_default='ACTIVE')
|
||||
create_by = Column(String(64), nullable=False, server_default='')
|
||||
create_time = Column(DateTime, nullable=False, default=datetime.now)
|
||||
update_by = Column(String(64), nullable=False, server_default='')
|
||||
update_time = Column(DateTime, nullable=False, default=datetime.now)
|
||||
closed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True)
|
||||
closed_at = Column(DateTime, nullable=True)
|
||||
purged_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True)
|
||||
purged_at = Column(DateTime, nullable=True)
|
||||
purge_summary = Column(Text, nullable=True)
|
||||
preview_action = Column(String(16), nullable=True)
|
||||
preview_token_hash = Column(CHAR(64), nullable=True)
|
||||
preview_scope_hash = Column(CHAR(64), nullable=True)
|
||||
preview_expires_at = Column(DateTime, nullable=True)
|
||||
remark = Column(String(500), nullable=True)
|
||||
|
||||
|
||||
class BizTestBatchUser(Base):
|
||||
"""测试数据批次与用户关联。"""
|
||||
|
||||
__tablename__ = 'biz_test_batch_user'
|
||||
|
||||
batch_id = Column(BigInteger, ForeignKey('biz_test_batch.batch_id'), primary_key=True)
|
||||
user_id = Column(BigInteger, ForeignKey('sys_user.user_id'), primary_key=True)
|
||||
create_by = Column(String(64), nullable=False, server_default='')
|
||||
create_time = Column(DateTime, nullable=False, default=datetime.now)
|
||||
@@ -0,0 +1,116 @@
|
||||
from datetime import datetime
|
||||
from typing import Annotated, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field
|
||||
from pydantic.alias_generators import to_camel
|
||||
|
||||
from module_business.domain.enums import TestBatchStatus
|
||||
|
||||
PositiveId = Annotated[int, Field(gt=0)]
|
||||
|
||||
|
||||
class TestBatchApiModel(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
alias_generator=to_camel,
|
||||
from_attributes=True,
|
||||
populate_by_name=True,
|
||||
extra='forbid',
|
||||
)
|
||||
|
||||
|
||||
class TestBatchCreateModel(TestBatchApiModel):
|
||||
batch_name: str = Field(min_length=1, max_length=100)
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class TestBatchEditModel(TestBatchApiModel):
|
||||
remark: str | None = Field(default=None, max_length=500)
|
||||
|
||||
|
||||
class TestBatchUserAssignModel(TestBatchApiModel):
|
||||
user_ids: list[PositiveId]
|
||||
|
||||
|
||||
class TestBatchModel(TestBatchApiModel):
|
||||
batch_id: PositiveId
|
||||
batch_code: str
|
||||
batch_name: str
|
||||
status: TestBatchStatus
|
||||
remark: str | None = None
|
||||
create_by: str
|
||||
create_time: datetime
|
||||
update_by: str
|
||||
update_time: datetime
|
||||
closed_by: int | None = None
|
||||
closed_at: datetime | None = None
|
||||
purged_by: int | None = None
|
||||
purged_at: datetime | None = None
|
||||
purge_summary: dict[str, int] | None = None
|
||||
|
||||
|
||||
class TestBatchOptionModel(TestBatchApiModel):
|
||||
batch_id: PositiveId
|
||||
batch_code: str
|
||||
batch_name: str
|
||||
status: TestBatchStatus
|
||||
|
||||
|
||||
class BatchImpactModel(TestBatchApiModel):
|
||||
table_name: str
|
||||
label: str
|
||||
count: int = Field(ge=0)
|
||||
keys: list[str]
|
||||
|
||||
|
||||
class TestBatchDetailModel(TestBatchModel):
|
||||
user_ids: list[int]
|
||||
data_summary: list[BatchImpactModel]
|
||||
|
||||
|
||||
class TestBatchPreviewModel(TestBatchApiModel):
|
||||
batch_id: PositiveId
|
||||
batch_name: str
|
||||
preview_token: str
|
||||
expires_at: datetime
|
||||
total_count: int = Field(ge=0)
|
||||
impacts: list[BatchImpactModel]
|
||||
|
||||
|
||||
class PurgePreviewModel(TestBatchPreviewModel):
|
||||
online_purge_allowed: bool
|
||||
online_purge_limit: int = Field(ge=0)
|
||||
blocking_reason: str | None = None
|
||||
|
||||
|
||||
AdoptionRootType = Literal[
|
||||
'strain',
|
||||
'customer',
|
||||
'site',
|
||||
'line',
|
||||
'warehouse',
|
||||
'pallet',
|
||||
'inbound',
|
||||
'filling',
|
||||
'shipment',
|
||||
'usage',
|
||||
'return',
|
||||
]
|
||||
|
||||
|
||||
class AdoptionRootModel(TestBatchApiModel):
|
||||
resource_type: AdoptionRootType
|
||||
resource_ids: list[PositiveId] = Field(min_length=1)
|
||||
|
||||
|
||||
class AdoptionPreviewRequestModel(TestBatchApiModel):
|
||||
roots: list[AdoptionRootModel] = Field(min_length=1)
|
||||
|
||||
|
||||
class AdoptionExecuteRequestModel(AdoptionPreviewRequestModel):
|
||||
batch_name: str = Field(min_length=1, max_length=100)
|
||||
preview_token: str = Field(min_length=32, max_length=128)
|
||||
|
||||
|
||||
class PurgeExecuteRequestModel(TestBatchApiModel):
|
||||
batch_name: str = Field(min_length=1, max_length=100)
|
||||
preview_token: str = Field(min_length=32, max_length=128)
|
||||
@@ -0,0 +1,137 @@
|
||||
-- 测试数据批次隔离:MySQL 增量补丁
|
||||
-- 本补丁仅增加可空归属字段,不回填既有数据。
|
||||
|
||||
CREATE TABLE biz_test_batch (
|
||||
batch_id BIGINT NOT NULL AUTO_INCREMENT COMMENT '测试数据批次ID',
|
||||
batch_code VARCHAR(64) NOT NULL COMMENT '批次编码',
|
||||
batch_name VARCHAR(100) NOT NULL COMMENT '批次名称',
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE' COMMENT '批次状态',
|
||||
create_by VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建者',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
update_by VARCHAR(64) NOT NULL DEFAULT '' COMMENT '更新者',
|
||||
update_time DATETIME NOT NULL COMMENT '更新时间',
|
||||
closed_by BIGINT NULL COMMENT '关闭人ID',
|
||||
closed_at DATETIME NULL COMMENT '关闭时间',
|
||||
purged_by BIGINT NULL COMMENT '清理人ID',
|
||||
purged_at DATETIME NULL COMMENT '清理时间',
|
||||
purge_summary TEXT NULL COMMENT '清理摘要JSON',
|
||||
preview_action VARCHAR(16) NULL COMMENT '预览动作',
|
||||
preview_token_hash CHAR(64) NULL COMMENT '预览令牌摘要',
|
||||
preview_scope_hash CHAR(64) NULL COMMENT '预览范围摘要',
|
||||
preview_expires_at DATETIME NULL COMMENT '预览过期时间',
|
||||
remark VARCHAR(500) NULL COMMENT '备注',
|
||||
PRIMARY KEY (batch_id),
|
||||
CONSTRAINT uq_biz_test_batch_code UNIQUE (batch_code),
|
||||
CONSTRAINT ck_biz_test_batch_status CHECK (status IN ('ACTIVE', 'CLOSED', 'PURGED')),
|
||||
CONSTRAINT ck_biz_test_batch_preview_action CHECK (
|
||||
preview_action IS NULL OR preview_action IN ('ADOPT', 'PURGE')
|
||||
),
|
||||
CONSTRAINT fk_biz_test_batch_closed_by FOREIGN KEY (closed_by) REFERENCES sys_user (user_id),
|
||||
CONSTRAINT fk_biz_test_batch_purged_by FOREIGN KEY (purged_by) REFERENCES sys_user (user_id)
|
||||
) ENGINE=InnoDB COMMENT='测试数据批次';
|
||||
|
||||
CREATE TABLE biz_test_batch_user (
|
||||
batch_id BIGINT NOT NULL COMMENT '测试数据批次ID',
|
||||
user_id BIGINT NOT NULL COMMENT '用户ID',
|
||||
create_by VARCHAR(64) NOT NULL DEFAULT '' COMMENT '创建者',
|
||||
create_time DATETIME NOT NULL COMMENT '创建时间',
|
||||
PRIMARY KEY (batch_id, user_id),
|
||||
CONSTRAINT fk_biz_test_batch_user_batch FOREIGN KEY (batch_id) REFERENCES biz_test_batch (batch_id),
|
||||
CONSTRAINT fk_biz_test_batch_user_user FOREIGN KEY (user_id) REFERENCES sys_user (user_id)
|
||||
) ENGINE=InnoDB COMMENT='测试数据批次与用户关联';
|
||||
|
||||
ALTER TABLE biz_strain
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_strain_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_strain_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_customer
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_customer_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_customer_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_customer_site
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_customer_site_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_customer_site_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_production_line
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_production_line_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_production_line_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_warehouse
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_warehouse_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_warehouse_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_pallet_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_pallet_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_inbound_order
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_inbound_order_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_inbound_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_inbound_item
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_inbound_item_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_inbound_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_filling_record
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_filling_record_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_filling_record_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_shipment_order
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_shipment_order_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_shipment_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_shipment_item
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_shipment_item_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_shipment_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_usage_record
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_usage_record_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_usage_record_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_return_order
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_return_order_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_return_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_return_item
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_return_item_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_return_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet_inventory
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_pallet_inventory_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_pallet_inventory_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet_event
|
||||
ADD COLUMN test_batch_id BIGINT NULL COMMENT '测试数据批次ID;NULL表示正式数据',
|
||||
ADD INDEX idx_biz_pallet_event_test_batch_id (test_batch_id),
|
||||
ADD CONSTRAINT fk_biz_pallet_event_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
@@ -0,0 +1,139 @@
|
||||
-- 测试数据批次隔离:PostgreSQL 增量补丁
|
||||
-- 本补丁仅增加可空归属字段,不回填既有数据。
|
||||
|
||||
CREATE TABLE biz_test_batch (
|
||||
batch_id BIGSERIAL NOT NULL,
|
||||
batch_code VARCHAR(64) NOT NULL,
|
||||
batch_name VARCHAR(100) NOT NULL,
|
||||
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
|
||||
create_by VARCHAR(64) NOT NULL DEFAULT '',
|
||||
create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
update_by VARCHAR(64) NOT NULL DEFAULT '',
|
||||
update_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
closed_by BIGINT NULL,
|
||||
closed_at TIMESTAMP WITHOUT TIME ZONE NULL,
|
||||
purged_by BIGINT NULL,
|
||||
purged_at TIMESTAMP WITHOUT TIME ZONE NULL,
|
||||
purge_summary TEXT NULL,
|
||||
preview_action VARCHAR(16) NULL,
|
||||
preview_token_hash CHAR(64) NULL,
|
||||
preview_scope_hash CHAR(64) NULL,
|
||||
preview_expires_at TIMESTAMP WITHOUT TIME ZONE NULL,
|
||||
remark VARCHAR(500) NULL,
|
||||
PRIMARY KEY (batch_id),
|
||||
CONSTRAINT uq_biz_test_batch_code UNIQUE (batch_code),
|
||||
CONSTRAINT ck_biz_test_batch_status CHECK (status IN ('ACTIVE', 'CLOSED', 'PURGED')),
|
||||
CONSTRAINT ck_biz_test_batch_preview_action CHECK (
|
||||
preview_action IS NULL OR preview_action IN ('ADOPT', 'PURGE')
|
||||
),
|
||||
CONSTRAINT fk_biz_test_batch_closed_by FOREIGN KEY (closed_by) REFERENCES sys_user (user_id),
|
||||
CONSTRAINT fk_biz_test_batch_purged_by FOREIGN KEY (purged_by) REFERENCES sys_user (user_id)
|
||||
);
|
||||
COMMENT ON TABLE biz_test_batch IS '测试数据批次';
|
||||
|
||||
CREATE TABLE biz_test_batch_user (
|
||||
batch_id BIGINT NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
create_by VARCHAR(64) NOT NULL DEFAULT '',
|
||||
create_time TIMESTAMP WITHOUT TIME ZONE NOT NULL,
|
||||
PRIMARY KEY (batch_id, user_id),
|
||||
CONSTRAINT fk_biz_test_batch_user_batch FOREIGN KEY (batch_id) REFERENCES biz_test_batch (batch_id),
|
||||
CONSTRAINT fk_biz_test_batch_user_user FOREIGN KEY (user_id) REFERENCES sys_user (user_id)
|
||||
);
|
||||
COMMENT ON TABLE biz_test_batch_user IS '测试数据批次与用户关联';
|
||||
|
||||
ALTER TABLE biz_strain ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_strain.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_strain_test_batch_id ON biz_strain (test_batch_id);
|
||||
ALTER TABLE biz_strain ADD CONSTRAINT fk_biz_strain_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_customer ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_customer.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_customer_test_batch_id ON biz_customer (test_batch_id);
|
||||
ALTER TABLE biz_customer ADD CONSTRAINT fk_biz_customer_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_customer_site ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_customer_site.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_customer_site_test_batch_id ON biz_customer_site (test_batch_id);
|
||||
ALTER TABLE biz_customer_site ADD CONSTRAINT fk_biz_customer_site_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_production_line ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_production_line.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_production_line_test_batch_id ON biz_production_line (test_batch_id);
|
||||
ALTER TABLE biz_production_line ADD CONSTRAINT fk_biz_production_line_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_warehouse ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_warehouse.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_warehouse_test_batch_id ON biz_warehouse (test_batch_id);
|
||||
ALTER TABLE biz_warehouse ADD CONSTRAINT fk_biz_warehouse_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_pallet.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_pallet_test_batch_id ON biz_pallet (test_batch_id);
|
||||
ALTER TABLE biz_pallet ADD CONSTRAINT fk_biz_pallet_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_inbound_order ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_inbound_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_inbound_order_test_batch_id ON biz_inbound_order (test_batch_id);
|
||||
ALTER TABLE biz_inbound_order ADD CONSTRAINT fk_biz_inbound_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_inbound_item ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_inbound_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_inbound_item_test_batch_id ON biz_inbound_item (test_batch_id);
|
||||
ALTER TABLE biz_inbound_item ADD CONSTRAINT fk_biz_inbound_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_filling_record ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_filling_record.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_filling_record_test_batch_id ON biz_filling_record (test_batch_id);
|
||||
ALTER TABLE biz_filling_record ADD CONSTRAINT fk_biz_filling_record_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_shipment_order ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_shipment_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_shipment_order_test_batch_id ON biz_shipment_order (test_batch_id);
|
||||
ALTER TABLE biz_shipment_order ADD CONSTRAINT fk_biz_shipment_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_shipment_item ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_shipment_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_shipment_item_test_batch_id ON biz_shipment_item (test_batch_id);
|
||||
ALTER TABLE biz_shipment_item ADD CONSTRAINT fk_biz_shipment_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_usage_record ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_usage_record.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_usage_record_test_batch_id ON biz_usage_record (test_batch_id);
|
||||
ALTER TABLE biz_usage_record ADD CONSTRAINT fk_biz_usage_record_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_return_order ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_return_order.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_return_order_test_batch_id ON biz_return_order (test_batch_id);
|
||||
ALTER TABLE biz_return_order ADD CONSTRAINT fk_biz_return_order_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_return_item ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_return_item.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_return_item_test_batch_id ON biz_return_item (test_batch_id);
|
||||
ALTER TABLE biz_return_item ADD CONSTRAINT fk_biz_return_item_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet_inventory ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_pallet_inventory.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_pallet_inventory_test_batch_id ON biz_pallet_inventory (test_batch_id);
|
||||
ALTER TABLE biz_pallet_inventory ADD CONSTRAINT fk_biz_pallet_inventory_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
|
||||
ALTER TABLE biz_pallet_event ADD COLUMN test_batch_id BIGINT NULL;
|
||||
COMMENT ON COLUMN biz_pallet_event.test_batch_id IS '测试数据批次ID;NULL表示正式数据';
|
||||
CREATE INDEX idx_biz_pallet_event_test_batch_id ON biz_pallet_event (test_batch_id);
|
||||
ALTER TABLE biz_pallet_event ADD CONSTRAINT fk_biz_pallet_event_test_batch_id
|
||||
FOREIGN KEY (test_batch_id) REFERENCES biz_test_batch (batch_id);
|
||||
@@ -19,6 +19,8 @@ drop table if exists biz_customer_site;
|
||||
drop table if exists biz_customer;
|
||||
drop table if exists biz_warehouse;
|
||||
drop table if exists biz_strain;
|
||||
drop table if exists biz_test_batch_user;
|
||||
drop table if exists biz_test_batch;
|
||||
|
||||
-- ----------------------------
|
||||
-- 1、部门表
|
||||
@@ -1076,8 +1078,48 @@ $$ IMMUTABLE STRICT LANGUAGE PLPGSQL;
|
||||
-- ----------------------------
|
||||
-- 20、托盘流转业务表
|
||||
-- ----------------------------
|
||||
create table biz_test_batch (
|
||||
batch_id bigserial not null,
|
||||
batch_code varchar(64) not null,
|
||||
batch_name varchar(100) not null,
|
||||
status varchar(16) not null default 'ACTIVE',
|
||||
create_by varchar(64) not null default '',
|
||||
create_time timestamp without time zone not null,
|
||||
update_by varchar(64) not null default '',
|
||||
update_time timestamp without time zone not null,
|
||||
closed_by bigint,
|
||||
closed_at timestamp without time zone,
|
||||
purged_by bigint,
|
||||
purged_at timestamp without time zone,
|
||||
purge_summary text,
|
||||
preview_action varchar(16),
|
||||
preview_token_hash char(64),
|
||||
preview_scope_hash char(64),
|
||||
preview_expires_at timestamp without time zone,
|
||||
remark varchar(500),
|
||||
primary key (batch_id),
|
||||
constraint uq_biz_test_batch_code unique (batch_code),
|
||||
constraint ck_biz_test_batch_status check (status in ('ACTIVE', 'CLOSED', 'PURGED')),
|
||||
constraint ck_biz_test_batch_preview_action check (preview_action is null or preview_action in ('ADOPT', 'PURGE')),
|
||||
constraint fk_biz_test_batch_closed_by foreign key (closed_by) references sys_user(user_id),
|
||||
constraint fk_biz_test_batch_purged_by foreign key (purged_by) references sys_user(user_id)
|
||||
);
|
||||
comment on table biz_test_batch is '测试数据批次';
|
||||
|
||||
create table biz_test_batch_user (
|
||||
batch_id bigint not null,
|
||||
user_id bigint not null,
|
||||
create_by varchar(64) not null default '',
|
||||
create_time timestamp without time zone not null,
|
||||
primary key (batch_id, user_id),
|
||||
constraint fk_biz_test_batch_user_batch foreign key (batch_id) references biz_test_batch(batch_id),
|
||||
constraint fk_biz_test_batch_user_user foreign key (user_id) references sys_user(user_id)
|
||||
);
|
||||
comment on table biz_test_batch_user is '测试数据批次与用户关联';
|
||||
|
||||
create table biz_strain (
|
||||
strain_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
strain_code varchar(64) not null,
|
||||
strain_name varchar(100) not null,
|
||||
status char(1) not null default '0',
|
||||
@@ -1088,11 +1130,13 @@ create table biz_strain (
|
||||
remark varchar(500) default null,
|
||||
primary key (strain_id),
|
||||
constraint uq_biz_strain_code unique (strain_code),
|
||||
constraint fk_biz_strain_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_strain_status check (status in ('0', '1'))
|
||||
);
|
||||
|
||||
create table biz_warehouse (
|
||||
warehouse_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
warehouse_code varchar(64) not null,
|
||||
warehouse_name varchar(100) not null,
|
||||
address varchar(500),
|
||||
@@ -1104,11 +1148,13 @@ create table biz_warehouse (
|
||||
remark varchar(500) default null,
|
||||
primary key (warehouse_id),
|
||||
constraint uq_biz_warehouse_code unique (warehouse_code),
|
||||
constraint fk_biz_warehouse_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_warehouse_status check (status in ('0', '1'))
|
||||
);
|
||||
|
||||
create table biz_customer (
|
||||
customer_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
customer_code varchar(64) not null,
|
||||
customer_name varchar(100) not null,
|
||||
status char(1) not null default '0',
|
||||
@@ -1119,11 +1165,13 @@ create table biz_customer (
|
||||
remark varchar(500) default null,
|
||||
primary key (customer_id),
|
||||
constraint uq_biz_customer_code unique (customer_code),
|
||||
constraint fk_biz_customer_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_customer_status check (status in ('0', '1'))
|
||||
);
|
||||
|
||||
create table biz_customer_site (
|
||||
site_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
customer_id bigint not null,
|
||||
site_code varchar(64) not null,
|
||||
site_name varchar(100) not null,
|
||||
@@ -1136,12 +1184,14 @@ create table biz_customer_site (
|
||||
remark varchar(500) default null,
|
||||
primary key (site_id),
|
||||
constraint uq_biz_customer_site_customer_code unique (customer_id, site_code),
|
||||
constraint fk_biz_customer_site_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_customer_site_status check (status in ('0', '1')),
|
||||
constraint fk_biz_customer_site_customer foreign key (customer_id) references biz_customer(customer_id)
|
||||
);
|
||||
|
||||
create table biz_production_line (
|
||||
line_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
site_id bigint not null,
|
||||
line_code varchar(64) not null,
|
||||
line_name varchar(100) not null,
|
||||
@@ -1153,12 +1203,14 @@ create table biz_production_line (
|
||||
remark varchar(500) default null,
|
||||
primary key (line_id),
|
||||
constraint uq_biz_production_line_site_code unique (site_id, line_code),
|
||||
constraint fk_biz_production_line_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_production_line_status check (status in ('0', '1')),
|
||||
constraint fk_biz_production_line_site foreign key (site_id) references biz_customer_site(site_id)
|
||||
);
|
||||
|
||||
create table biz_pallet (
|
||||
pallet_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
pallet_code varchar(64) not null,
|
||||
qr_token varchar(128) not null,
|
||||
capacity_packages integer not null,
|
||||
@@ -1171,6 +1223,7 @@ create table biz_pallet (
|
||||
primary key (pallet_id),
|
||||
constraint uq_biz_pallet_code unique (pallet_code),
|
||||
constraint uq_biz_pallet_qr_token unique (qr_token),
|
||||
constraint fk_biz_pallet_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint ck_biz_pallet_capacity_packages check (capacity_packages > 0),
|
||||
constraint ck_biz_pallet_asset_status check (asset_status in ('0', '1'))
|
||||
);
|
||||
@@ -1197,6 +1250,7 @@ create table biz_user_site (
|
||||
|
||||
create table biz_inbound_order (
|
||||
inbound_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
inbound_no varchar(64) not null,
|
||||
warehouse_id bigint not null,
|
||||
status varchar(32) not null default 'DRAFT',
|
||||
@@ -1213,12 +1267,14 @@ create table biz_inbound_order (
|
||||
constraint uq_biz_inbound_order_no unique (inbound_no),
|
||||
constraint uq_biz_inbound_order_warehouse_confirm_idempotency unique (warehouse_id, confirm_idempotency_key),
|
||||
constraint ck_biz_inbound_order_status check (status in ('DRAFT', 'CONFIRMED')),
|
||||
constraint fk_biz_inbound_order_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id),
|
||||
constraint fk_biz_inbound_order_warehouse foreign key (warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_inbound_order_confirmer foreign key (confirmed_by) references sys_user(user_id)
|
||||
);
|
||||
|
||||
create table biz_inbound_item (
|
||||
inbound_item_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
inbound_id bigint not null,
|
||||
pallet_id bigint not null,
|
||||
create_by varchar(64) default '',
|
||||
@@ -1226,11 +1282,13 @@ create table biz_inbound_item (
|
||||
primary key (inbound_item_id),
|
||||
constraint uq_biz_inbound_item_order_pallet unique (inbound_id, pallet_id),
|
||||
constraint fk_biz_inbound_item_order foreign key (inbound_id) references biz_inbound_order(inbound_id),
|
||||
constraint fk_biz_inbound_item_pallet foreign key (pallet_id) references biz_pallet(pallet_id)
|
||||
constraint fk_biz_inbound_item_pallet foreign key (pallet_id) references biz_pallet(pallet_id),
|
||||
constraint fk_biz_inbound_item_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_filling_record (
|
||||
filling_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
filling_no varchar(64) not null,
|
||||
pallet_id bigint not null,
|
||||
warehouse_id bigint not null,
|
||||
@@ -1260,11 +1318,13 @@ create table biz_filling_record (
|
||||
constraint fk_biz_filling_record_pallet foreign key (pallet_id) references biz_pallet(pallet_id),
|
||||
constraint fk_biz_filling_record_warehouse foreign key (warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_filling_record_strain foreign key (strain_id) references biz_strain(strain_id),
|
||||
constraint fk_biz_filling_record_operator foreign key (operator_id) references sys_user(user_id)
|
||||
constraint fk_biz_filling_record_operator foreign key (operator_id) references sys_user(user_id),
|
||||
constraint fk_biz_filling_record_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_shipment_order (
|
||||
shipment_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
shipment_no varchar(64) not null,
|
||||
source_warehouse_id bigint not null,
|
||||
target_site_id bigint not null,
|
||||
@@ -1284,11 +1344,13 @@ create table biz_shipment_order (
|
||||
constraint ck_biz_shipment_order_status check (status in ('DRAFT', 'CONFIRMED')),
|
||||
constraint fk_biz_shipment_order_warehouse foreign key (source_warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_shipment_order_site foreign key (target_site_id) references biz_customer_site(site_id),
|
||||
constraint fk_biz_shipment_order_confirmer foreign key (confirmed_by) references sys_user(user_id)
|
||||
constraint fk_biz_shipment_order_confirmer foreign key (confirmed_by) references sys_user(user_id),
|
||||
constraint fk_biz_shipment_order_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_shipment_item (
|
||||
shipment_item_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
shipment_id bigint not null,
|
||||
pallet_id bigint not null,
|
||||
active_filling_id bigint,
|
||||
@@ -1300,11 +1362,13 @@ create table biz_shipment_item (
|
||||
constraint ck_biz_shipment_item_package_qty check (package_qty is null or package_qty > 0),
|
||||
constraint fk_biz_shipment_item_order foreign key (shipment_id) references biz_shipment_order(shipment_id),
|
||||
constraint fk_biz_shipment_item_pallet foreign key (pallet_id) references biz_pallet(pallet_id),
|
||||
constraint fk_biz_shipment_item_filling foreign key (active_filling_id) references biz_filling_record(filling_id)
|
||||
constraint fk_biz_shipment_item_filling foreign key (active_filling_id) references biz_filling_record(filling_id),
|
||||
constraint fk_biz_shipment_item_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_usage_record (
|
||||
usage_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
usage_no varchar(64) not null,
|
||||
pallet_id bigint not null,
|
||||
active_filling_id bigint not null,
|
||||
@@ -1325,11 +1389,13 @@ create table biz_usage_record (
|
||||
constraint fk_biz_usage_record_filling foreign key (active_filling_id) references biz_filling_record(filling_id),
|
||||
constraint fk_biz_usage_record_site foreign key (site_id) references biz_customer_site(site_id),
|
||||
constraint fk_biz_usage_record_line foreign key (line_id) references biz_production_line(line_id),
|
||||
constraint fk_biz_usage_record_operator foreign key (operator_id) references sys_user(user_id)
|
||||
constraint fk_biz_usage_record_operator foreign key (operator_id) references sys_user(user_id),
|
||||
constraint fk_biz_usage_record_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_return_order (
|
||||
return_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
return_no varchar(64) not null,
|
||||
source_site_id bigint not null,
|
||||
target_warehouse_id bigint not null,
|
||||
@@ -1355,11 +1421,13 @@ create table biz_return_order (
|
||||
constraint fk_biz_return_order_site foreign key (source_site_id) references biz_customer_site(site_id),
|
||||
constraint fk_biz_return_order_warehouse foreign key (target_warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_return_order_requester foreign key (requested_by) references sys_user(user_id),
|
||||
constraint fk_biz_return_order_confirmer foreign key (confirmed_by) references sys_user(user_id)
|
||||
constraint fk_biz_return_order_confirmer foreign key (confirmed_by) references sys_user(user_id),
|
||||
constraint fk_biz_return_order_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_return_item (
|
||||
return_item_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
return_id bigint not null,
|
||||
pallet_id bigint not null,
|
||||
active_filling_id_snapshot bigint,
|
||||
@@ -1371,11 +1439,13 @@ create table biz_return_item (
|
||||
constraint ck_biz_return_item_remaining_packages_snapshot check (remaining_packages_snapshot >= 0),
|
||||
constraint fk_biz_return_item_order foreign key (return_id) references biz_return_order(return_id),
|
||||
constraint fk_biz_return_item_pallet foreign key (pallet_id) references biz_pallet(pallet_id),
|
||||
constraint fk_biz_return_item_filling foreign key (active_filling_id_snapshot) references biz_filling_record(filling_id)
|
||||
constraint fk_biz_return_item_filling foreign key (active_filling_id_snapshot) references biz_filling_record(filling_id),
|
||||
constraint fk_biz_return_item_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_pallet_event (
|
||||
event_id bigserial not null,
|
||||
test_batch_id bigint null,
|
||||
pallet_id bigint not null,
|
||||
event_seq integer not null,
|
||||
event_type varchar(32) not null,
|
||||
@@ -1411,11 +1481,13 @@ create table biz_pallet_event (
|
||||
constraint fk_biz_pallet_event_after_warehouse foreign key (after_warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_pallet_event_after_site foreign key (after_site_id) references biz_customer_site(site_id),
|
||||
constraint fk_biz_pallet_event_after_line foreign key (after_line_id) references biz_production_line(line_id),
|
||||
constraint fk_biz_pallet_event_operator foreign key (operator_id) references sys_user(user_id)
|
||||
constraint fk_biz_pallet_event_operator foreign key (operator_id) references sys_user(user_id),
|
||||
constraint fk_biz_pallet_event_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
create table biz_pallet_inventory (
|
||||
pallet_id bigint not null,
|
||||
test_batch_id bigint null,
|
||||
active_filling_id bigint,
|
||||
warehouse_id bigint,
|
||||
site_id bigint,
|
||||
@@ -1442,9 +1514,43 @@ create table biz_pallet_inventory (
|
||||
constraint fk_biz_pallet_inventory_warehouse foreign key (warehouse_id) references biz_warehouse(warehouse_id),
|
||||
constraint fk_biz_pallet_inventory_site foreign key (site_id) references biz_customer_site(site_id),
|
||||
constraint fk_biz_pallet_inventory_line foreign key (current_line_id) references biz_production_line(line_id),
|
||||
constraint fk_biz_pallet_inventory_event foreign key (last_event_id) references biz_pallet_event(event_id)
|
||||
constraint fk_biz_pallet_inventory_event foreign key (last_event_id) references biz_pallet_event(event_id),
|
||||
constraint fk_biz_pallet_inventory_test_batch_id foreign key (test_batch_id) references biz_test_batch(batch_id)
|
||||
);
|
||||
|
||||
comment on column biz_strain.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_strain_test_batch_id on biz_strain (test_batch_id);
|
||||
comment on column biz_customer.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_customer_test_batch_id on biz_customer (test_batch_id);
|
||||
comment on column biz_customer_site.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_customer_site_test_batch_id on biz_customer_site (test_batch_id);
|
||||
comment on column biz_production_line.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_production_line_test_batch_id on biz_production_line (test_batch_id);
|
||||
comment on column biz_warehouse.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_warehouse_test_batch_id on biz_warehouse (test_batch_id);
|
||||
comment on column biz_pallet.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_pallet_test_batch_id on biz_pallet (test_batch_id);
|
||||
comment on column biz_inbound_order.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_inbound_order_test_batch_id on biz_inbound_order (test_batch_id);
|
||||
comment on column biz_inbound_item.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_inbound_item_test_batch_id on biz_inbound_item (test_batch_id);
|
||||
comment on column biz_filling_record.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_filling_record_test_batch_id on biz_filling_record (test_batch_id);
|
||||
comment on column biz_shipment_order.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_shipment_order_test_batch_id on biz_shipment_order (test_batch_id);
|
||||
comment on column biz_shipment_item.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_shipment_item_test_batch_id on biz_shipment_item (test_batch_id);
|
||||
comment on column biz_usage_record.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_usage_record_test_batch_id on biz_usage_record (test_batch_id);
|
||||
comment on column biz_return_order.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_return_order_test_batch_id on biz_return_order (test_batch_id);
|
||||
comment on column biz_return_item.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_return_item_test_batch_id on biz_return_item (test_batch_id);
|
||||
comment on column biz_pallet_inventory.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_pallet_inventory_test_batch_id on biz_pallet_inventory (test_batch_id);
|
||||
comment on column biz_pallet_event.test_batch_id is '测试数据批次ID;NULL表示正式数据';
|
||||
create index idx_biz_pallet_event_test_batch_id on biz_pallet_event (test_batch_id);
|
||||
|
||||
-- ----------------------------
|
||||
-- 初始化-托盘业务一级菜单和权限
|
||||
-- ----------------------------
|
||||
|
||||
@@ -19,6 +19,8 @@ drop table if exists biz_customer_site;
|
||||
drop table if exists biz_customer;
|
||||
drop table if exists biz_warehouse;
|
||||
drop table if exists biz_strain;
|
||||
drop table if exists biz_test_batch_user;
|
||||
drop table if exists biz_test_batch;
|
||||
|
||||
-- ----------------------------
|
||||
-- 1、部门表
|
||||
@@ -811,9 +813,49 @@ create table gen_table_column (
|
||||
-- ----------------------------
|
||||
-- 20、托盘业务表(按依赖创建)
|
||||
-- ----------------------------
|
||||
-- 测试数据批次
|
||||
create table biz_test_batch (
|
||||
batch_id bigint(20) not null auto_increment comment '测试数据批次ID',
|
||||
batch_code varchar(64) not null comment '批次编码',
|
||||
batch_name varchar(100) not null comment '批次名称',
|
||||
status varchar(16) not null default 'ACTIVE' comment '批次状态',
|
||||
create_by varchar(64) not null default '' comment '创建者',
|
||||
create_time datetime not null comment '创建时间',
|
||||
update_by varchar(64) not null default '' comment '更新者',
|
||||
update_time datetime not null comment '更新时间',
|
||||
closed_by bigint(20) comment '关闭人ID',
|
||||
closed_at datetime comment '关闭时间',
|
||||
purged_by bigint(20) comment '清理人ID',
|
||||
purged_at datetime comment '清理时间',
|
||||
purge_summary text comment '清理摘要JSON',
|
||||
preview_action varchar(16) comment '预览动作',
|
||||
preview_token_hash char(64) comment '预览令牌摘要',
|
||||
preview_scope_hash char(64) comment '预览范围摘要',
|
||||
preview_expires_at datetime comment '预览过期时间',
|
||||
remark varchar(500) comment '备注',
|
||||
primary key (batch_id),
|
||||
constraint uq_biz_test_batch_code unique (batch_code),
|
||||
constraint ck_biz_test_batch_status check (status in ('ACTIVE', 'CLOSED', 'PURGED')),
|
||||
constraint ck_biz_test_batch_preview_action check (preview_action is null or preview_action in ('ADOPT', 'PURGE')),
|
||||
constraint fk_biz_test_batch_closed_by foreign key (closed_by) references sys_user (user_id),
|
||||
constraint fk_biz_test_batch_purged_by foreign key (purged_by) references sys_user (user_id)
|
||||
) engine=innodb comment = '测试数据批次';
|
||||
|
||||
-- 测试数据批次与用户关联
|
||||
create table biz_test_batch_user (
|
||||
batch_id bigint(20) not null comment '测试数据批次ID',
|
||||
user_id bigint(20) not null comment '用户ID',
|
||||
create_by varchar(64) not null default '' comment '创建者',
|
||||
create_time datetime not null comment '创建时间',
|
||||
primary key (batch_id, user_id),
|
||||
constraint fk_biz_test_batch_user_batch foreign key (batch_id) references biz_test_batch (batch_id),
|
||||
constraint fk_biz_test_batch_user_user foreign key (user_id) references sys_user (user_id)
|
||||
) engine=innodb comment = '测试数据批次与用户关联';
|
||||
|
||||
-- 菌种主数据表
|
||||
create table biz_strain (
|
||||
strain_id bigint(20) not null auto_increment comment '菌种ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
strain_code varchar(64) not null comment '菌种编码',
|
||||
strain_name varchar(100) not null comment '菌种名称',
|
||||
status char(1) not null default '0' comment '状态(0正常 1停用)',
|
||||
@@ -823,13 +865,16 @@ create table biz_strain (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (strain_id),
|
||||
key idx_biz_strain_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_strain_code unique (strain_code),
|
||||
constraint fk_biz_strain_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_strain_status check (status in ('0', '1'))
|
||||
) engine=innodb comment = '菌种主数据表';
|
||||
|
||||
-- 仓库主数据表
|
||||
create table biz_warehouse (
|
||||
warehouse_id bigint(20) not null auto_increment comment '仓库ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
warehouse_code varchar(64) not null comment '仓库编码',
|
||||
warehouse_name varchar(100) not null comment '仓库名称',
|
||||
address varchar(500) comment '仓库地址',
|
||||
@@ -840,13 +885,16 @@ create table biz_warehouse (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (warehouse_id),
|
||||
key idx_biz_warehouse_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_warehouse_code unique (warehouse_code),
|
||||
constraint fk_biz_warehouse_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_warehouse_status check (status in ('0', '1'))
|
||||
) engine=innodb comment = '仓库主数据表';
|
||||
|
||||
-- 客户主数据表
|
||||
create table biz_customer (
|
||||
customer_id bigint(20) not null auto_increment comment '客户ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
customer_code varchar(64) not null comment '客户编码',
|
||||
customer_name varchar(100) not null comment '客户名称',
|
||||
status char(1) not null default '0' comment '状态(0正常 1停用)',
|
||||
@@ -856,13 +904,16 @@ create table biz_customer (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (customer_id),
|
||||
key idx_biz_customer_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_customer_code unique (customer_code),
|
||||
constraint fk_biz_customer_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_customer_status check (status in ('0', '1'))
|
||||
) engine=innodb comment = '客户主数据表';
|
||||
|
||||
-- 客户现场主数据表
|
||||
create table biz_customer_site (
|
||||
site_id bigint(20) not null auto_increment comment '现场ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
customer_id bigint(20) not null comment '客户ID',
|
||||
site_code varchar(64) not null comment '现场编码',
|
||||
site_name varchar(100) not null comment '现场名称',
|
||||
@@ -874,7 +925,9 @@ create table biz_customer_site (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (site_id),
|
||||
key idx_biz_customer_site_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_customer_site_customer_code unique (customer_id, site_code),
|
||||
constraint fk_biz_customer_site_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint fk_biz_customer_site_customer foreign key (customer_id) references biz_customer (customer_id),
|
||||
constraint ck_biz_customer_site_status check (status in ('0', '1'))
|
||||
) engine=innodb comment = '客户现场主数据表';
|
||||
@@ -882,6 +935,7 @@ create table biz_customer_site (
|
||||
-- 客户现场产线主数据表
|
||||
create table biz_production_line (
|
||||
line_id bigint(20) not null auto_increment comment '产线ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
site_id bigint(20) not null comment '现场ID',
|
||||
line_code varchar(64) not null comment '产线编码',
|
||||
line_name varchar(100) not null comment '产线名称',
|
||||
@@ -892,7 +946,9 @@ create table biz_production_line (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (line_id),
|
||||
key idx_biz_production_line_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_production_line_site_code unique (site_id, line_code),
|
||||
constraint fk_biz_production_line_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint fk_biz_production_line_site foreign key (site_id) references biz_customer_site (site_id),
|
||||
constraint ck_biz_production_line_status check (status in ('0', '1'))
|
||||
) engine=innodb comment = '客户现场产线主数据表';
|
||||
@@ -900,6 +956,7 @@ create table biz_production_line (
|
||||
-- 托盘资产主数据表
|
||||
create table biz_pallet (
|
||||
pallet_id bigint(20) not null auto_increment comment '托盘ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
pallet_code varchar(64) not null comment '托盘编号',
|
||||
qr_token varchar(128) not null comment '二维码固定标识',
|
||||
capacity_packages int not null comment '容量包数',
|
||||
@@ -910,8 +967,10 @@ create table biz_pallet (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (pallet_id),
|
||||
key idx_biz_pallet_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_pallet_code unique (pallet_code),
|
||||
constraint uq_biz_pallet_qr_token unique (qr_token),
|
||||
constraint fk_biz_pallet_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_pallet_capacity_packages check (capacity_packages > 0),
|
||||
constraint ck_biz_pallet_asset_status check (asset_status in ('0', '1'))
|
||||
) engine=innodb comment = '托盘资产主数据表';
|
||||
@@ -941,6 +1000,7 @@ create table biz_user_site (
|
||||
-- 首次入库单
|
||||
create table biz_inbound_order (
|
||||
inbound_id bigint(20) not null auto_increment comment '入库单ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
inbound_no varchar(64) not null comment '入库单号',
|
||||
warehouse_id bigint(20) not null comment '仓库ID',
|
||||
status varchar(32) not null default 'DRAFT' comment '单据状态',
|
||||
@@ -954,29 +1014,35 @@ create table biz_inbound_order (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (inbound_id),
|
||||
key idx_biz_inbound_order_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_inbound_order_no unique (inbound_no),
|
||||
constraint uq_biz_inbound_order_warehouse_confirm_idempotency unique (warehouse_id, confirm_idempotency_key),
|
||||
constraint fk_biz_inbound_order_warehouse foreign key (warehouse_id) references biz_warehouse (warehouse_id),
|
||||
constraint fk_biz_inbound_order_confirmed_by foreign key (confirmed_by) references sys_user (user_id),
|
||||
constraint fk_biz_inbound_order_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_inbound_order_status check (status in ('DRAFT', 'CONFIRMED'))
|
||||
) engine=innodb comment = '首次入库单';
|
||||
|
||||
-- 首次入库单托盘明细
|
||||
create table biz_inbound_item (
|
||||
inbound_item_id bigint(20) not null auto_increment comment '入库明细ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
inbound_id bigint(20) not null comment '入库单ID',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
create_by varchar(64) default '' comment '创建者',
|
||||
create_time datetime comment '创建时间',
|
||||
primary key (inbound_item_id),
|
||||
key idx_biz_inbound_item_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_inbound_item_order_pallet unique (inbound_id, pallet_id),
|
||||
constraint fk_biz_inbound_item_order foreign key (inbound_id) references biz_inbound_order (inbound_id),
|
||||
constraint fk_biz_inbound_item_pallet foreign key (pallet_id) references biz_pallet (pallet_id)
|
||||
constraint fk_biz_inbound_item_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
constraint fk_biz_inbound_item_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id)
|
||||
) engine=innodb comment = '首次入库单托盘明细';
|
||||
|
||||
-- 托盘装填记录
|
||||
create table biz_filling_record (
|
||||
filling_id bigint(20) not null auto_increment comment '装填记录ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
filling_no varchar(64) not null comment '装填单号',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
warehouse_id bigint(20) not null comment '仓库ID',
|
||||
@@ -998,6 +1064,7 @@ create table biz_filling_record (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (filling_id),
|
||||
key idx_biz_filling_record_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_filling_record_no unique (filling_no),
|
||||
constraint uq_biz_filling_record_warehouse_idempotency unique (warehouse_id, idempotency_key),
|
||||
constraint uq_biz_filling_record_pallet_active_slot unique (pallet_id, active_slot),
|
||||
@@ -1005,6 +1072,7 @@ create table biz_filling_record (
|
||||
constraint fk_biz_filling_record_warehouse foreign key (warehouse_id) references biz_warehouse (warehouse_id),
|
||||
constraint fk_biz_filling_record_strain foreign key (strain_id) references biz_strain (strain_id),
|
||||
constraint fk_biz_filling_record_operator foreign key (operator_id) references sys_user (user_id),
|
||||
constraint fk_biz_filling_record_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_filling_record_initial_packages check (initial_packages > 0),
|
||||
constraint ck_biz_filling_record_active_slot check (active_slot is null or active_slot = 'ACTIVE')
|
||||
) engine=innodb comment = '托盘装填记录';
|
||||
@@ -1012,6 +1080,7 @@ create table biz_filling_record (
|
||||
-- 整托发货单
|
||||
create table biz_shipment_order (
|
||||
shipment_id bigint(20) not null auto_increment comment '发货单ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
shipment_no varchar(64) not null comment '发货单号',
|
||||
source_warehouse_id bigint(20) not null comment '来源仓库ID',
|
||||
target_site_id bigint(20) not null comment '目标现场ID',
|
||||
@@ -1026,17 +1095,20 @@ create table biz_shipment_order (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (shipment_id),
|
||||
key idx_biz_shipment_order_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_shipment_order_no unique (shipment_no),
|
||||
constraint uq_biz_shipment_order_route_confirm_idempotency unique (source_warehouse_id, target_site_id, confirm_idempotency_key),
|
||||
constraint fk_biz_shipment_order_warehouse foreign key (source_warehouse_id) references biz_warehouse (warehouse_id),
|
||||
constraint fk_biz_shipment_order_site foreign key (target_site_id) references biz_customer_site (site_id),
|
||||
constraint fk_biz_shipment_order_confirmed_by foreign key (confirmed_by) references sys_user (user_id),
|
||||
constraint fk_biz_shipment_order_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_shipment_order_status check (status in ('DRAFT', 'CONFIRMED'))
|
||||
) engine=innodb comment = '整托发货单';
|
||||
|
||||
-- 整托发货明细
|
||||
create table biz_shipment_item (
|
||||
shipment_item_id bigint(20) not null auto_increment comment '发货明细ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
shipment_id bigint(20) not null comment '发货单ID',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
active_filling_id bigint(20) comment '确认时活动装填记录ID',
|
||||
@@ -1044,16 +1116,19 @@ create table biz_shipment_item (
|
||||
create_by varchar(64) default '' comment '创建者',
|
||||
create_time datetime comment '创建时间',
|
||||
primary key (shipment_item_id),
|
||||
key idx_biz_shipment_item_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_shipment_item_order_pallet unique (shipment_id, pallet_id),
|
||||
constraint fk_biz_shipment_item_order foreign key (shipment_id) references biz_shipment_order (shipment_id),
|
||||
constraint fk_biz_shipment_item_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
constraint fk_biz_shipment_item_filling foreign key (active_filling_id) references biz_filling_record (filling_id),
|
||||
constraint fk_biz_shipment_item_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_shipment_item_package_qty check (package_qty is null or package_qty > 0)
|
||||
) engine=innodb comment = '整托发货明细';
|
||||
|
||||
-- 客户现场使用事实记录
|
||||
create table biz_usage_record (
|
||||
usage_id bigint(20) not null auto_increment comment '使用记录ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
usage_no varchar(64) not null comment '使用记录号',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
active_filling_id bigint(20) not null comment '活动装填记录ID',
|
||||
@@ -1066,6 +1141,7 @@ create table biz_usage_record (
|
||||
operator_id bigint(20) not null comment '操作人ID',
|
||||
occurred_at datetime not null comment '发生时间',
|
||||
primary key (usage_id),
|
||||
key idx_biz_usage_record_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_usage_record_no unique (usage_no),
|
||||
constraint uq_biz_usage_record_site_idempotency unique (site_id, idempotency_key),
|
||||
constraint fk_biz_usage_record_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
@@ -1073,6 +1149,7 @@ create table biz_usage_record (
|
||||
constraint fk_biz_usage_record_site foreign key (site_id) references biz_customer_site (site_id),
|
||||
constraint fk_biz_usage_record_line foreign key (line_id) references biz_production_line (line_id),
|
||||
constraint fk_biz_usage_record_operator foreign key (operator_id) references sys_user (user_id),
|
||||
constraint fk_biz_usage_record_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_usage_record_used_packages check (used_packages > 0),
|
||||
constraint ck_biz_usage_record_remaining_packages_after check (remaining_packages_after >= 0)
|
||||
) engine=innodb comment = '客户现场使用事实记录';
|
||||
@@ -1080,6 +1157,7 @@ create table biz_usage_record (
|
||||
-- 托盘退回单
|
||||
create table biz_return_order (
|
||||
return_id bigint(20) not null auto_increment comment '退回单ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
return_no varchar(64) not null comment '退回单号',
|
||||
source_site_id bigint(20) not null comment '来源现场ID',
|
||||
target_warehouse_id bigint(20) not null comment '目标仓库ID',
|
||||
@@ -1098,6 +1176,7 @@ create table biz_return_order (
|
||||
update_time datetime comment '更新时间',
|
||||
remark varchar(500) default null comment '备注',
|
||||
primary key (return_id),
|
||||
key idx_biz_return_order_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_return_order_no unique (return_no),
|
||||
constraint uq_biz_return_order_route_request_idempotency unique (source_site_id, target_warehouse_id, request_idempotency_key),
|
||||
constraint uq_biz_return_order_route_confirm_idempotency unique (source_site_id, target_warehouse_id, confirm_idempotency_key),
|
||||
@@ -1105,12 +1184,14 @@ create table biz_return_order (
|
||||
constraint fk_biz_return_order_warehouse foreign key (target_warehouse_id) references biz_warehouse (warehouse_id),
|
||||
constraint fk_biz_return_order_requested_by foreign key (requested_by) references sys_user (user_id),
|
||||
constraint fk_biz_return_order_confirmed_by foreign key (confirmed_by) references sys_user (user_id),
|
||||
constraint fk_biz_return_order_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_return_order_status check (status in ('REQUESTED', 'CONFIRMED'))
|
||||
) engine=innodb comment = '托盘退回单';
|
||||
|
||||
-- 托盘退回明细
|
||||
create table biz_return_item (
|
||||
return_item_id bigint(20) not null auto_increment comment '退回明细ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
return_id bigint(20) not null comment '退回单ID',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
active_filling_id_snapshot bigint(20) comment '申请时活动装填记录快照',
|
||||
@@ -1118,16 +1199,19 @@ create table biz_return_item (
|
||||
create_by varchar(64) default '' comment '创建者',
|
||||
create_time datetime comment '创建时间',
|
||||
primary key (return_item_id),
|
||||
key idx_biz_return_item_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_return_item_order_pallet unique (return_id, pallet_id),
|
||||
constraint fk_biz_return_item_order foreign key (return_id) references biz_return_order (return_id),
|
||||
constraint fk_biz_return_item_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
constraint fk_biz_return_item_filling foreign key (active_filling_id_snapshot) references biz_filling_record (filling_id),
|
||||
constraint fk_biz_return_item_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_return_item_remaining_packages_snapshot check (remaining_packages_snapshot >= 0)
|
||||
) engine=innodb comment = '托盘退回明细';
|
||||
|
||||
-- 托盘只追加流转事件;必须先于库存快照创建
|
||||
create table biz_pallet_event (
|
||||
event_id bigint(20) not null auto_increment comment '事件ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
event_seq int not null comment '托盘内事件序号',
|
||||
event_type varchar(32) not null comment '事件类型',
|
||||
@@ -1148,6 +1232,7 @@ create table biz_pallet_event (
|
||||
idempotency_key varchar(64) not null comment '幂等键',
|
||||
request_hash varchar(64) not null comment '请求摘要',
|
||||
primary key (event_id),
|
||||
key idx_biz_pallet_event_test_batch_id (test_batch_id),
|
||||
constraint uq_biz_pallet_event_pallet_seq unique (pallet_id, event_seq),
|
||||
constraint uq_biz_pallet_event_pallet_idempotency unique (pallet_id, idempotency_key),
|
||||
constraint fk_biz_pallet_event_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
@@ -1158,6 +1243,7 @@ create table biz_pallet_event (
|
||||
constraint fk_biz_pallet_event_after_site foreign key (after_site_id) references biz_customer_site (site_id),
|
||||
constraint fk_biz_pallet_event_after_line foreign key (after_line_id) references biz_production_line (line_id),
|
||||
constraint fk_biz_pallet_event_operator foreign key (operator_id) references sys_user (user_id),
|
||||
constraint fk_biz_pallet_event_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_pallet_event_event_type check (
|
||||
event_type in (
|
||||
'INBOUND_CONFIRMED',
|
||||
@@ -1173,6 +1259,7 @@ create table biz_pallet_event (
|
||||
-- 托盘当前库存、位置和流转状态
|
||||
create table biz_pallet_inventory (
|
||||
pallet_id bigint(20) not null comment '托盘ID',
|
||||
test_batch_id bigint(20) null comment '测试数据批次ID;NULL表示正式数据',
|
||||
active_filling_id bigint(20) comment '当前活动装填记录ID',
|
||||
warehouse_id bigint(20) comment '当前仓库ID',
|
||||
site_id bigint(20) comment '当前现场ID',
|
||||
@@ -1183,12 +1270,14 @@ create table biz_pallet_inventory (
|
||||
version int not null default 0 comment '并发版本号',
|
||||
updated_at datetime not null comment '更新时间',
|
||||
primary key (pallet_id),
|
||||
key idx_biz_pallet_inventory_test_batch_id (test_batch_id),
|
||||
constraint fk_biz_pallet_inventory_pallet foreign key (pallet_id) references biz_pallet (pallet_id),
|
||||
constraint fk_biz_pallet_inventory_filling foreign key (active_filling_id) references biz_filling_record (filling_id),
|
||||
constraint fk_biz_pallet_inventory_warehouse foreign key (warehouse_id) references biz_warehouse (warehouse_id),
|
||||
constraint fk_biz_pallet_inventory_site foreign key (site_id) references biz_customer_site (site_id),
|
||||
constraint fk_biz_pallet_inventory_line foreign key (current_line_id) references biz_production_line (line_id),
|
||||
constraint fk_biz_pallet_inventory_event foreign key (last_event_id) references biz_pallet_event (event_id),
|
||||
constraint fk_biz_pallet_inventory_test_batch_id foreign key (test_batch_id) references biz_test_batch (batch_id),
|
||||
constraint ck_biz_pallet_inventory_flow_state check (
|
||||
flow_state in (
|
||||
'UNSTOCKED',
|
||||
|
||||
@@ -1,11 +1,32 @@
|
||||
import unittest
|
||||
|
||||
from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, UniqueConstraint
|
||||
from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, Text, UniqueConstraint
|
||||
from sqlalchemy.dialects import mysql, postgresql
|
||||
from sqlalchemy.schema import CreateColumn
|
||||
from sqlalchemy.schema import CreateColumn, CreateTable
|
||||
|
||||
from config.database import Base
|
||||
from module_business.entity.do import master_do, operation_do
|
||||
from module_admin.entity.do import user_do
|
||||
from module_business.entity.do import master_do, operation_do, test_batch_do
|
||||
|
||||
EXPECTED_TEST_BATCH_TABLES = {'biz_test_batch', 'biz_test_batch_user'}
|
||||
TEST_BATCH_OWNED_TABLES = {
|
||||
'biz_strain',
|
||||
'biz_customer',
|
||||
'biz_customer_site',
|
||||
'biz_production_line',
|
||||
'biz_warehouse',
|
||||
'biz_pallet',
|
||||
'biz_inbound_order',
|
||||
'biz_inbound_item',
|
||||
'biz_filling_record',
|
||||
'biz_shipment_order',
|
||||
'biz_shipment_item',
|
||||
'biz_usage_record',
|
||||
'biz_return_order',
|
||||
'biz_return_item',
|
||||
'biz_pallet_inventory',
|
||||
'biz_pallet_event',
|
||||
}
|
||||
|
||||
EXPECTED_COLUMNS = {
|
||||
'biz_strain': {
|
||||
@@ -892,6 +913,136 @@ EXPECTED_UNIQUE_SETS = {
|
||||
},
|
||||
}
|
||||
|
||||
for table_name in TEST_BATCH_OWNED_TABLES:
|
||||
EXPECTED_COLUMNS[table_name].add('test_batch_id')
|
||||
EXPECTED_COLUMN_TYPES[table_name]['test_batch_id'] = (BigInteger, None)
|
||||
EXPECTED_NULLABILITY[table_name]['test_batch_id'] = True
|
||||
EXPECTED_FOREIGN_KEYS[table_name].add(('test_batch_id', 'biz_test_batch.batch_id'))
|
||||
|
||||
EXPECTED_COLUMNS.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
'batch_id',
|
||||
'batch_code',
|
||||
'batch_name',
|
||||
'status',
|
||||
'create_by',
|
||||
'create_time',
|
||||
'update_by',
|
||||
'update_time',
|
||||
'closed_by',
|
||||
'closed_at',
|
||||
'purged_by',
|
||||
'purged_at',
|
||||
'purge_summary',
|
||||
'preview_action',
|
||||
'preview_token_hash',
|
||||
'preview_scope_hash',
|
||||
'preview_expires_at',
|
||||
'remark',
|
||||
},
|
||||
'biz_test_batch_user': {'batch_id', 'user_id', 'create_by', 'create_time'},
|
||||
}
|
||||
)
|
||||
EXPECTED_COLUMN_TYPES.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
'batch_id': (BigInteger, None),
|
||||
'batch_code': (String, 64),
|
||||
'batch_name': (String, 100),
|
||||
'status': (String, 16),
|
||||
'create_by': (String, 64),
|
||||
'create_time': (DateTime, None),
|
||||
'update_by': (String, 64),
|
||||
'update_time': (DateTime, None),
|
||||
'closed_by': (BigInteger, None),
|
||||
'closed_at': (DateTime, None),
|
||||
'purged_by': (BigInteger, None),
|
||||
'purged_at': (DateTime, None),
|
||||
'purge_summary': (Text, None),
|
||||
'preview_action': (String, 16),
|
||||
'preview_token_hash': (CHAR, 64),
|
||||
'preview_scope_hash': (CHAR, 64),
|
||||
'preview_expires_at': (DateTime, None),
|
||||
'remark': (String, 500),
|
||||
},
|
||||
'biz_test_batch_user': {
|
||||
'batch_id': (BigInteger, None),
|
||||
'user_id': (BigInteger, None),
|
||||
'create_by': (String, 64),
|
||||
'create_time': (DateTime, None),
|
||||
},
|
||||
}
|
||||
)
|
||||
EXPECTED_NULLABILITY.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
'batch_id': False,
|
||||
'batch_code': False,
|
||||
'batch_name': False,
|
||||
'status': False,
|
||||
'create_by': False,
|
||||
'create_time': False,
|
||||
'update_by': False,
|
||||
'update_time': False,
|
||||
'closed_by': True,
|
||||
'closed_at': True,
|
||||
'purged_by': True,
|
||||
'purged_at': True,
|
||||
'purge_summary': True,
|
||||
'preview_action': True,
|
||||
'preview_token_hash': True,
|
||||
'preview_scope_hash': True,
|
||||
'preview_expires_at': True,
|
||||
'remark': True,
|
||||
},
|
||||
'biz_test_batch_user': {
|
||||
'batch_id': False,
|
||||
'user_id': False,
|
||||
'create_by': False,
|
||||
'create_time': False,
|
||||
},
|
||||
}
|
||||
)
|
||||
EXPECTED_CALLABLE_DATETIME_DEFAULTS.update(
|
||||
{
|
||||
('biz_test_batch', 'create_time'),
|
||||
('biz_test_batch', 'update_time'),
|
||||
('biz_test_batch_user', 'create_time'),
|
||||
}
|
||||
)
|
||||
EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS.update(
|
||||
{
|
||||
('biz_test_batch', 'create_by'),
|
||||
('biz_test_batch', 'update_by'),
|
||||
('biz_test_batch_user', 'create_by'),
|
||||
}
|
||||
)
|
||||
EXPECTED_PRIMARY_KEYS.update(
|
||||
{
|
||||
'biz_test_batch': ('batch_id',),
|
||||
'biz_test_batch_user': ('batch_id', 'user_id'),
|
||||
}
|
||||
)
|
||||
EXPECTED_FOREIGN_KEYS.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
('closed_by', 'sys_user.user_id'),
|
||||
('purged_by', 'sys_user.user_id'),
|
||||
},
|
||||
'biz_test_batch_user': {
|
||||
('batch_id', 'biz_test_batch.batch_id'),
|
||||
('user_id', 'sys_user.user_id'),
|
||||
},
|
||||
}
|
||||
)
|
||||
EXPECTED_UNIQUE_SETS.update(
|
||||
{
|
||||
'biz_test_batch': {frozenset({'batch_code'})},
|
||||
'biz_test_batch_user': set(),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def _unique_column_sets(table: Table) -> set[frozenset[str]]:
|
||||
return {
|
||||
@@ -910,6 +1061,16 @@ def _normalized_check_sql(table: Table) -> dict[str, str]:
|
||||
|
||||
|
||||
class BusinessModelContractTest(unittest.TestCase):
|
||||
def test_batch_related_tables_compile_for_mysql_and_postgresql(self) -> None:
|
||||
self.assertIs(Base.metadata.tables['sys_user'], user_do.SysUser.__table__)
|
||||
batch_tables = EXPECTED_TEST_BATCH_TABLES | TEST_BATCH_OWNED_TABLES
|
||||
self.assertEqual(18, len(batch_tables))
|
||||
for table_name in batch_tables:
|
||||
for dialect_name, dialect in (('mysql', mysql.dialect()), ('postgresql', postgresql.dialect())):
|
||||
with self.subTest(table_name=table_name, dialect=dialect_name):
|
||||
compiled = str(CreateTable(Base.metadata.tables[table_name]).compile(dialect=dialect))
|
||||
self.assertIn(table_name, compiled)
|
||||
|
||||
def test_exact_business_tables_are_registered(self) -> None:
|
||||
expected = {
|
||||
'biz_strain',
|
||||
@@ -930,7 +1091,7 @@ class BusinessModelContractTest(unittest.TestCase):
|
||||
'biz_return_item',
|
||||
'biz_pallet_inventory',
|
||||
'biz_pallet_event',
|
||||
}
|
||||
} | EXPECTED_TEST_BATCH_TABLES
|
||||
actual = {name for name in Base.metadata.tables if name.startswith('biz_')}
|
||||
self.assertEqual(expected, actual)
|
||||
|
||||
@@ -954,6 +1115,8 @@ class BusinessModelContractTest(unittest.TestCase):
|
||||
operation_do.BizReturnItem: 'biz_return_item',
|
||||
operation_do.BizPalletInventory: 'biz_pallet_inventory',
|
||||
operation_do.BizPalletEvent: 'biz_pallet_event',
|
||||
test_batch_do.BizTestBatch: 'biz_test_batch',
|
||||
test_batch_do.BizTestBatchUser: 'biz_test_batch_user',
|
||||
}
|
||||
self.assertEqual(set(EXPECTED_COLUMNS), set(models.values()))
|
||||
for model, table_name in models.items():
|
||||
@@ -1032,6 +1195,7 @@ class BusinessModelContractTest(unittest.TestCase):
|
||||
_, separator, compiled_default = compiled_column.partition(' DEFAULT ')
|
||||
if separator:
|
||||
compiled_default = compiled_default.split(' COMMENT ', maxsplit=1)[0].strip()
|
||||
compiled_default = compiled_default.removesuffix(' NOT NULL')
|
||||
if compiled_default != "''":
|
||||
violations.append((dialect_name, table_name, column_name, compiled_default))
|
||||
self.assertEqual([], violations)
|
||||
@@ -1058,6 +1222,26 @@ class BusinessModelContractTest(unittest.TestCase):
|
||||
with self.subTest(table_name=table_name):
|
||||
self.assertEqual(expected_unique_sets, _unique_column_sets(Base.metadata.tables[table_name]))
|
||||
|
||||
def test_all_owned_models_have_nullable_indexed_batch_fk(self) -> None:
|
||||
for table_name in TEST_BATCH_OWNED_TABLES:
|
||||
table = Base.metadata.tables[table_name]
|
||||
column = table.c.test_batch_id
|
||||
self.assertTrue(column.nullable, table_name)
|
||||
self.assertTrue(column.index, table_name)
|
||||
fk = next(iter(column.foreign_keys))
|
||||
self.assertEqual('biz_test_batch.batch_id', fk.target_fullname)
|
||||
self.assertIsNone(fk.ondelete)
|
||||
|
||||
def test_test_batch_model_defaults_and_comments_match_contract(self) -> None:
|
||||
table = Base.metadata.tables['biz_test_batch']
|
||||
self.assertEqual('测试数据批次', table.comment)
|
||||
self.assertEqual('ACTIVE', str(table.c.status.server_default.arg))
|
||||
for table_name in TEST_BATCH_OWNED_TABLES:
|
||||
self.assertEqual(
|
||||
'测试数据批次ID;NULL表示正式数据',
|
||||
Base.metadata.tables[table_name].c.test_batch_id.comment,
|
||||
)
|
||||
|
||||
def test_pallet_identifiers_are_unique(self) -> None:
|
||||
table = Base.metadata.tables['biz_pallet']
|
||||
unique_columns = {column.name for column in table.columns if column.unique}
|
||||
@@ -1065,6 +1249,10 @@ class BusinessModelContractTest(unittest.TestCase):
|
||||
|
||||
def test_checks_lock_quantities_states_active_slot_and_location(self) -> None:
|
||||
expected_checks = {
|
||||
'biz_test_batch': {
|
||||
'ck_biz_test_batch_status': "statusIN('ACTIVE','CLOSED','PURGED')",
|
||||
'ck_biz_test_batch_preview_action': "preview_actionISNULLORpreview_actionIN('ADOPT','PURGE')",
|
||||
},
|
||||
'biz_strain': {'ck_biz_strain_status': "statusIN('0','1')"},
|
||||
'biz_warehouse': {'ck_biz_warehouse_status': "statusIN('0','1')"},
|
||||
'biz_customer': {'ck_biz_customer_status': "statusIN('0','1')"},
|
||||
|
||||
@@ -9,11 +9,33 @@ INITIALIZERS = ('shierfeng-fastapi.sql', 'shierfeng-fastapi-pg.sql')
|
||||
PATCH_PATH = SQL_ROOT / 'patches/20260724_pallet_workflow_mysql.sql'
|
||||
MENU_PROMOTION_PATCH_PATH = SQL_ROOT / 'patches/20260727_promote_business_menus_mysql.sql'
|
||||
BUSINESS_MENU_ICON_PATCH_PATH = SQL_ROOT / 'patches/20260728_add_business_menu_icons_mysql.sql'
|
||||
TEST_BATCH_MYSQL_PATCH_PATH = SQL_ROOT / 'patches/20260922_test_data_batch_mysql.sql'
|
||||
TEST_BATCH_PG_PATCH_PATH = SQL_ROOT / 'patches/20260922_test_data_batch_pg.sql'
|
||||
SYS_MENU_VALUE_COUNT = 20
|
||||
SYS_MENU_PERMS_INDEX = 13
|
||||
SYS_MENU_ICON_INDEX = 14
|
||||
REMOVED_AI_DICT_CODES = set(range(33, 70))
|
||||
|
||||
EXPECTED_TEST_BATCH_TABLES = {'biz_test_batch', 'biz_test_batch_user'}
|
||||
TEST_BATCH_OWNED_TABLES = {
|
||||
'biz_strain',
|
||||
'biz_customer',
|
||||
'biz_customer_site',
|
||||
'biz_production_line',
|
||||
'biz_warehouse',
|
||||
'biz_pallet',
|
||||
'biz_inbound_order',
|
||||
'biz_inbound_item',
|
||||
'biz_filling_record',
|
||||
'biz_shipment_order',
|
||||
'biz_shipment_item',
|
||||
'biz_usage_record',
|
||||
'biz_return_order',
|
||||
'biz_return_item',
|
||||
'biz_pallet_inventory',
|
||||
'biz_pallet_event',
|
||||
}
|
||||
|
||||
EXPECTED_TABLES = {
|
||||
'biz_strain',
|
||||
'biz_warehouse',
|
||||
@@ -346,6 +368,83 @@ EXPECTED_CHECKS = {
|
||||
},
|
||||
}
|
||||
|
||||
LEGACY_EXPECTED_TABLES = set(EXPECTED_TABLES)
|
||||
LEGACY_EXPECTED_COLUMNS = {table: set(columns) for table, columns in EXPECTED_COLUMNS.items()}
|
||||
LEGACY_EXPECTED_PRIMARY_KEYS = dict(EXPECTED_PRIMARY_KEYS)
|
||||
LEGACY_EXPECTED_UNIQUE_KEYS = {table: set(keys) for table, keys in EXPECTED_UNIQUE_KEYS.items()}
|
||||
LEGACY_EXPECTED_FOREIGN_KEYS = {table: set(keys) for table, keys in EXPECTED_FOREIGN_KEYS.items()}
|
||||
LEGACY_EXPECTED_CHECKS = {table: set(checks) for table, checks in EXPECTED_CHECKS.items()}
|
||||
|
||||
EXPECTED_TABLES |= EXPECTED_TEST_BATCH_TABLES
|
||||
for table_name in TEST_BATCH_OWNED_TABLES:
|
||||
EXPECTED_COLUMNS[table_name].add('test_batch_id')
|
||||
EXPECTED_FOREIGN_KEYS[table_name].add(('test_batch_id', 'biz_test_batch.batch_id'))
|
||||
|
||||
EXPECTED_COLUMNS.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
'batch_id',
|
||||
'batch_code',
|
||||
'batch_name',
|
||||
'status',
|
||||
'create_by',
|
||||
'create_time',
|
||||
'update_by',
|
||||
'update_time',
|
||||
'closed_by',
|
||||
'closed_at',
|
||||
'purged_by',
|
||||
'purged_at',
|
||||
'purge_summary',
|
||||
'preview_action',
|
||||
'preview_token_hash',
|
||||
'preview_scope_hash',
|
||||
'preview_expires_at',
|
||||
'remark',
|
||||
},
|
||||
'biz_test_batch_user': {'batch_id', 'user_id', 'create_by', 'create_time'},
|
||||
}
|
||||
)
|
||||
EXPECTED_DATETIME_COLUMNS.update(
|
||||
{
|
||||
'biz_test_batch': {'create_time', 'update_time', 'closed_at', 'purged_at', 'preview_expires_at'},
|
||||
'biz_test_batch_user': {'create_time'},
|
||||
}
|
||||
)
|
||||
EXPECTED_PRIMARY_KEYS.update(
|
||||
{
|
||||
'biz_test_batch': ('batch_id',),
|
||||
'biz_test_batch_user': ('batch_id', 'user_id'),
|
||||
}
|
||||
)
|
||||
EXPECTED_UNIQUE_KEYS.update(
|
||||
{
|
||||
'biz_test_batch': {('batch_code',)},
|
||||
'biz_test_batch_user': set(),
|
||||
}
|
||||
)
|
||||
EXPECTED_FOREIGN_KEYS.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
('closed_by', 'sys_user.user_id'),
|
||||
('purged_by', 'sys_user.user_id'),
|
||||
},
|
||||
'biz_test_batch_user': {
|
||||
('batch_id', 'biz_test_batch.batch_id'),
|
||||
('user_id', 'sys_user.user_id'),
|
||||
},
|
||||
}
|
||||
)
|
||||
EXPECTED_CHECKS.update(
|
||||
{
|
||||
'biz_test_batch': {
|
||||
"statusin('active','closed','purged')",
|
||||
"preview_actionisnullorpreview_actionin('adopt','purge')",
|
||||
},
|
||||
'biz_test_batch_user': set(),
|
||||
}
|
||||
)
|
||||
|
||||
EXPECTED_PAGES = {
|
||||
502: ('菌种资料', 121, 1, 'strain', 'master/strain/index', 'master:strain:list'),
|
||||
503: ('客户资料', 121, 2, 'customer', 'master/customer/index', 'master:customer:list'),
|
||||
@@ -873,6 +972,74 @@ def _is_postgres_naive_timestamp_with_default_precision(definition: str) -> bool
|
||||
)
|
||||
|
||||
|
||||
def _assert_test_batch_sql_contract(
|
||||
test_case: unittest.TestCase,
|
||||
sql: str,
|
||||
*,
|
||||
dialect: str,
|
||||
is_patch: bool,
|
||||
) -> None:
|
||||
clean_sql = _strip_sql_comments(sql).replace('`', '')
|
||||
normalized = re.sub(r'\s+', ' ', clean_sql).strip().lower()
|
||||
tables = _create_table_bodies(sql)
|
||||
|
||||
test_case.assertNotRegex(normalized, r'\bon\s+delete\s+cascade\b')
|
||||
if is_patch:
|
||||
test_case.assertNotRegex(normalized, r'\bupdate\b')
|
||||
|
||||
for table_name in EXPECTED_TEST_BATCH_TABLES:
|
||||
test_case.assertIn(table_name, tables)
|
||||
columns, primary_key, unique_keys, foreign_keys, checks = _table_contract(tables[table_name])
|
||||
test_case.assertEqual(EXPECTED_COLUMNS[table_name], columns, table_name)
|
||||
test_case.assertEqual(EXPECTED_PRIMARY_KEYS[table_name], primary_key, table_name)
|
||||
test_case.assertEqual(EXPECTED_UNIQUE_KEYS[table_name], unique_keys, table_name)
|
||||
test_case.assertEqual(EXPECTED_FOREIGN_KEYS[table_name], foreign_keys, table_name)
|
||||
test_case.assertEqual(EXPECTED_CHECKS[table_name], checks, table_name)
|
||||
|
||||
create_batch = normalized.index('create table biz_test_batch (')
|
||||
create_batch_user = normalized.index('create table biz_test_batch_user (')
|
||||
owned_marker = 'alter table' if is_patch else 'create table'
|
||||
first_owned = min(normalized.index(f'{owned_marker} {table_name} ') for table_name in TEST_BATCH_OWNED_TABLES)
|
||||
test_case.assertLess(create_batch, create_batch_user)
|
||||
test_case.assertLess(create_batch_user, first_owned)
|
||||
|
||||
for table_name in TEST_BATCH_OWNED_TABLES:
|
||||
with test_case.subTest(dialect=dialect, patch=is_patch, table=table_name):
|
||||
if is_patch:
|
||||
test_case.assertRegex(
|
||||
normalized,
|
||||
rf'\balter table {table_name}\s+add column test_batch_id bigint null\b',
|
||||
)
|
||||
else:
|
||||
definitions = _column_definitions(tables[table_name])
|
||||
test_case.assertIn('test_batch_id', definitions)
|
||||
test_case.assertRegex(definitions['test_batch_id'], r'\bbigint\b')
|
||||
test_case.assertNotRegex(definitions['test_batch_id'], r'\bnot\s+null\b')
|
||||
|
||||
index_name = f'idx_{table_name}_test_batch_id'
|
||||
if dialect == 'mysql':
|
||||
index_pattern = rf'\b(?:add\s+)?(?:index|key)\s+{index_name}\s*\(\s*test_batch_id\s*\)'
|
||||
test_case.assertRegex(normalized, index_pattern)
|
||||
test_case.assertIn("comment '测试数据批次id;null表示正式数据'", normalized)
|
||||
else:
|
||||
index_pattern = (
|
||||
rf'\bcreate\s+index\s+{index_name}\s+on\s+{table_name}\s*\(\s*test_batch_id\s*\)'
|
||||
)
|
||||
test_case.assertRegex(normalized, index_pattern)
|
||||
test_case.assertRegex(
|
||||
normalized,
|
||||
rf"comment\s+on\s+column\s+{table_name}\.test_batch_id\s+is\s+"
|
||||
r"'测试数据批次id;null表示正式数据'",
|
||||
)
|
||||
|
||||
constraint_name = f'fk_{table_name}_test_batch_id'
|
||||
test_case.assertRegex(
|
||||
normalized,
|
||||
rf'\bconstraint\s+{constraint_name}\s+foreign\s+key\s*\(\s*test_batch_id\s*\)\s*'
|
||||
r'references\s+biz_test_batch\s*\(\s*batch_id\s*\)',
|
||||
)
|
||||
|
||||
|
||||
def _menu_rows(sql: str, menu_ids: set[int]) -> dict[int, list]:
|
||||
rows = _insert_rows(sql, 'sys_menu')
|
||||
selected = [row for row in rows if row and str(row[0]).isdigit() and int(row[0]) in menu_ids]
|
||||
@@ -1064,9 +1231,7 @@ def _assert_business_menu_icon_guard_primary_key(test_case: unittest.TestCase, s
|
||||
|
||||
def _assert_business_menu_icon_guard_structure(test_case: unittest.TestCase, sql: str) -> tuple[str, str]:
|
||||
normalized = [_normalized_sql_statement(statement) for statement in _sql_statements(sql)]
|
||||
guards = [
|
||||
statement for statement in normalized if statement.startswith('insert into business_menu_icon_guard ')
|
||||
]
|
||||
guards = [statement for statement in normalized if statement.startswith('insert into business_menu_icon_guard ')]
|
||||
test_case.assertEqual(2, len(guards))
|
||||
pre_guard, post_guard = guards
|
||||
identity_fields = (
|
||||
@@ -1128,6 +1293,23 @@ def _assert_business_menu_icon_guard_structure(test_case: unittest.TestCase, sql
|
||||
|
||||
|
||||
class SqlContractTest(unittest.TestCase):
|
||||
def test_test_batch_initializers_and_patches_match_contract(self) -> None:
|
||||
scripts = (
|
||||
(SQL_ROOT / 'shierfeng-fastapi.sql', 'mysql', False),
|
||||
(SQL_ROOT / 'shierfeng-fastapi-pg.sql', 'postgresql', False),
|
||||
(TEST_BATCH_MYSQL_PATCH_PATH, 'mysql', True),
|
||||
(TEST_BATCH_PG_PATCH_PATH, 'postgresql', True),
|
||||
)
|
||||
for path, dialect, is_patch in scripts:
|
||||
with self.subTest(path=path.name):
|
||||
self.assertTrue(path.is_file(), f'missing SQL: {path}')
|
||||
_assert_test_batch_sql_contract(
|
||||
self,
|
||||
path.read_text(encoding='utf-8'),
|
||||
dialect=dialect,
|
||||
is_patch=is_patch,
|
||||
)
|
||||
|
||||
def test_initializers_define_exact_business_table_set(self) -> None:
|
||||
for filename in INITIALIZERS:
|
||||
with self.subTest(filename=filename):
|
||||
@@ -1149,7 +1331,7 @@ class SqlContractTest(unittest.TestCase):
|
||||
self.assertEqual(EXPECTED_CHECKS[table], checks)
|
||||
|
||||
def test_postgres_business_datetimes_preserve_default_microsecond_precision(self) -> None:
|
||||
self.assertEqual(34, sum(len(columns) for columns in EXPECTED_DATETIME_COLUMNS.values()))
|
||||
self.assertEqual(40, sum(len(columns) for columns in EXPECTED_DATETIME_COLUMNS.values()))
|
||||
tables = _create_table_bodies((SQL_ROOT / 'shierfeng-fastapi-pg.sql').read_text(encoding='utf-8'))
|
||||
invalid_columns = []
|
||||
for table, expected_columns in EXPECTED_DATETIME_COLUMNS.items():
|
||||
@@ -1290,9 +1472,7 @@ class SqlContractTest(unittest.TestCase):
|
||||
self.assertEqual(1, normalized.count('start transaction'))
|
||||
self.assertEqual(1, normalized.count('commit'))
|
||||
transaction_body = normalized[start_index + 1 : commit_index]
|
||||
lock_statement = (
|
||||
'select menu_id from sys_menu where menu_id in (121, 122, 123) order by menu_id for update'
|
||||
)
|
||||
lock_statement = 'select menu_id from sys_menu where menu_id in (121, 122, 123) order by menu_id for update'
|
||||
expected_update = (
|
||||
"update sys_menu set icon = case menu_id when 121 then 'documentation' when 122 then 'build' "
|
||||
"when 123 then 'chart' else icon end where menu_id in (121, 122, 123)"
|
||||
@@ -1476,6 +1656,8 @@ class SqlContractTest(unittest.TestCase):
|
||||
'biz_customer',
|
||||
'biz_warehouse',
|
||||
'biz_strain',
|
||||
'biz_test_batch_user',
|
||||
'biz_test_batch',
|
||||
)
|
||||
for filename in INITIALIZERS:
|
||||
with self.subTest(filename=filename):
|
||||
@@ -1777,15 +1959,15 @@ class SqlContractTest(unittest.TestCase):
|
||||
self.assertLess(lower.index('ddl'), lower.index('dml'))
|
||||
self.assertEqual(18, len(re.findall(r'create\s+table\s+if\s+not\s+exists\s+`?biz_', lower)))
|
||||
tables = _create_table_bodies(raw)
|
||||
self.assertEqual(EXPECTED_TABLES, {table for table in tables if table.startswith('biz_')})
|
||||
for table in EXPECTED_TABLES:
|
||||
self.assertEqual(LEGACY_EXPECTED_TABLES, {table for table in tables if table.startswith('biz_')})
|
||||
for table in LEGACY_EXPECTED_TABLES:
|
||||
with self.subTest(table=table):
|
||||
columns, primary_key, unique_keys, foreign_keys, checks = _table_contract(tables[table])
|
||||
self.assertEqual(EXPECTED_COLUMNS[table], columns)
|
||||
self.assertEqual(EXPECTED_PRIMARY_KEYS[table], primary_key)
|
||||
self.assertEqual(EXPECTED_UNIQUE_KEYS[table], unique_keys)
|
||||
self.assertEqual(EXPECTED_FOREIGN_KEYS[table], foreign_keys)
|
||||
self.assertEqual(EXPECTED_CHECKS[table], checks)
|
||||
self.assertEqual(LEGACY_EXPECTED_COLUMNS[table], columns)
|
||||
self.assertEqual(LEGACY_EXPECTED_PRIMARY_KEYS[table], primary_key)
|
||||
self.assertEqual(LEGACY_EXPECTED_UNIQUE_KEYS[table], unique_keys)
|
||||
self.assertEqual(LEGACY_EXPECTED_FOREIGN_KEYS[table], foreign_keys)
|
||||
self.assertEqual(LEGACY_EXPECTED_CHECKS[table], checks)
|
||||
_assert_business_menu_fields(self, raw, LEGACY_PATCH_BUSINESS_MENU_FIELDS)
|
||||
_assert_business_permission_inventory(self, raw)
|
||||
patch_rows = _business_menu_rows(raw)
|
||||
@@ -1793,9 +1975,7 @@ class SqlContractTest(unittest.TestCase):
|
||||
compared_indexes = (0, 1, *range(4, 15))
|
||||
expected_legacy_rows = {
|
||||
menu_id: tuple(
|
||||
'#'
|
||||
if index == SYS_MENU_ICON_INDEX and menu_id in EXPECTED_BUSINESS_ROOT_ICONS
|
||||
else row[index]
|
||||
'#' if index == SYS_MENU_ICON_INDEX and menu_id in EXPECTED_BUSINESS_ROOT_ICONS else row[index]
|
||||
for index in compared_indexes
|
||||
)
|
||||
for menu_id, row in mysql_rows.items()
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import unittest
|
||||
from datetime import datetime
|
||||
|
||||
from pydantic import ValidationError
|
||||
from pydantic.alias_generators import to_camel
|
||||
@@ -69,6 +70,21 @@ from module_business.entity.vo.report_vo import (
|
||||
ShipmentReportModel,
|
||||
ShipmentReportQueryModel,
|
||||
)
|
||||
from module_business.entity.vo.test_batch_vo import (
|
||||
AdoptionExecuteRequestModel,
|
||||
AdoptionPreviewRequestModel,
|
||||
AdoptionRootModel,
|
||||
BatchImpactModel,
|
||||
PurgeExecuteRequestModel,
|
||||
PurgePreviewModel,
|
||||
TestBatchCreateModel,
|
||||
TestBatchDetailModel,
|
||||
TestBatchEditModel,
|
||||
TestBatchModel,
|
||||
TestBatchOptionModel,
|
||||
TestBatchPreviewModel,
|
||||
TestBatchUserAssignModel,
|
||||
)
|
||||
|
||||
MASTER_MODEL_FIELDS = {
|
||||
StrainModel: {
|
||||
@@ -549,6 +565,71 @@ REPORT_MODEL_FIELDS = {
|
||||
},
|
||||
}
|
||||
|
||||
TEST_BATCH_MODEL_FIELDS = {
|
||||
TestBatchCreateModel: {'batch_name', 'remark'},
|
||||
TestBatchEditModel: {'remark'},
|
||||
TestBatchUserAssignModel: {'user_ids'},
|
||||
TestBatchModel: {
|
||||
'batch_id',
|
||||
'batch_code',
|
||||
'batch_name',
|
||||
'status',
|
||||
'remark',
|
||||
'create_by',
|
||||
'create_time',
|
||||
'update_by',
|
||||
'update_time',
|
||||
'closed_by',
|
||||
'closed_at',
|
||||
'purged_by',
|
||||
'purged_at',
|
||||
'purge_summary',
|
||||
},
|
||||
TestBatchOptionModel: {'batch_id', 'batch_code', 'batch_name', 'status'},
|
||||
BatchImpactModel: {'table_name', 'label', 'count', 'keys'},
|
||||
TestBatchDetailModel: {
|
||||
'batch_id',
|
||||
'batch_code',
|
||||
'batch_name',
|
||||
'status',
|
||||
'remark',
|
||||
'create_by',
|
||||
'create_time',
|
||||
'update_by',
|
||||
'update_time',
|
||||
'closed_by',
|
||||
'closed_at',
|
||||
'purged_by',
|
||||
'purged_at',
|
||||
'purge_summary',
|
||||
'user_ids',
|
||||
'data_summary',
|
||||
},
|
||||
TestBatchPreviewModel: {
|
||||
'batch_id',
|
||||
'batch_name',
|
||||
'preview_token',
|
||||
'expires_at',
|
||||
'total_count',
|
||||
'impacts',
|
||||
},
|
||||
PurgePreviewModel: {
|
||||
'batch_id',
|
||||
'batch_name',
|
||||
'preview_token',
|
||||
'expires_at',
|
||||
'total_count',
|
||||
'impacts',
|
||||
'online_purge_allowed',
|
||||
'online_purge_limit',
|
||||
'blocking_reason',
|
||||
},
|
||||
AdoptionRootModel: {'resource_type', 'resource_ids'},
|
||||
AdoptionPreviewRequestModel: {'roots'},
|
||||
AdoptionExecuteRequestModel: {'roots', 'batch_name', 'preview_token'},
|
||||
PurgeExecuteRequestModel: {'batch_name', 'preview_token'},
|
||||
}
|
||||
|
||||
WRITE_MODELS = (
|
||||
StrainModel,
|
||||
DeleteStrainModel,
|
||||
@@ -761,7 +842,7 @@ PACKAGE_MODEL_PAYLOADS = {
|
||||
|
||||
class BusinessVoContractTest(unittest.TestCase):
|
||||
def test_all_models_have_exact_fields_and_camel_case_aliases(self) -> None:
|
||||
expected_models = MASTER_MODEL_FIELDS | OPERATION_MODEL_FIELDS | REPORT_MODEL_FIELDS
|
||||
expected_models = MASTER_MODEL_FIELDS | OPERATION_MODEL_FIELDS | REPORT_MODEL_FIELDS | TEST_BATCH_MODEL_FIELDS
|
||||
|
||||
for model_class, expected_fields in expected_models.items():
|
||||
with self.subTest(model=model_class.__name__):
|
||||
@@ -777,6 +858,44 @@ class BusinessVoContractTest(unittest.TestCase):
|
||||
with self.subTest(model=model_class.__name__):
|
||||
self.assertEqual('forbid', model_class.model_config.get('extra'))
|
||||
|
||||
def test_all_test_batch_models_forbid_extra_fields(self) -> None:
|
||||
for model_class in TEST_BATCH_MODEL_FIELDS:
|
||||
with self.subTest(model=model_class.__name__):
|
||||
self.assertEqual('forbid', model_class.model_config.get('extra'))
|
||||
|
||||
def test_test_batch_models_accept_snake_case_and_camel_case(self) -> None:
|
||||
camel_case = TestBatchCreateModel(batchName='验收批次', remark='camel')
|
||||
snake_case = TestBatchCreateModel(batch_name='验收批次', remark='snake')
|
||||
self.assertEqual('验收批次', camel_case.batch_name)
|
||||
self.assertEqual('验收批次', snake_case.batch_name)
|
||||
|
||||
def test_test_batch_edit_forbids_immutable_fields(self) -> None:
|
||||
for field_name, value in (('batchName', '新名称'), ('status', 'CLOSED')):
|
||||
with self.subTest(field=field_name), self.assertRaises(ValidationError):
|
||||
TestBatchEditModel.model_validate({'remark': None, field_name: value})
|
||||
|
||||
def test_test_batch_positive_ids_and_non_empty_roots_are_validated(self) -> None:
|
||||
with self.assertRaises(ValidationError):
|
||||
TestBatchUserAssignModel(userIds=[0])
|
||||
with self.assertRaises(ValidationError):
|
||||
AdoptionRootModel(resourceType='strain', resourceIds=[])
|
||||
with self.assertRaises(ValidationError):
|
||||
AdoptionPreviewRequestModel(roots=[])
|
||||
|
||||
def test_test_batch_status_rejects_unknown_value(self) -> None:
|
||||
with self.assertRaises(ValidationError) as context:
|
||||
TestBatchModel(
|
||||
batchId=1,
|
||||
batchCode='TB-1',
|
||||
batchName='验收批次',
|
||||
status='UNKNOWN',
|
||||
createBy='admin',
|
||||
createTime=datetime(2026, 9, 22),
|
||||
updateBy='admin',
|
||||
updateTime=datetime(2026, 9, 22),
|
||||
)
|
||||
self.assertIn(('status',), {tuple(error['loc']) for error in context.exception.errors()})
|
||||
|
||||
def test_page_queries_have_positive_defaults(self) -> None:
|
||||
for model_class in PAGE_QUERY_MODELS:
|
||||
with self.subTest(model=model_class.__name__):
|
||||
|
||||
Reference in New Issue
Block a user