测试:强化业务模型元数据契约

This commit is contained in:
焦龙言
2026-07-24 20:25:02 +08:00
parent f6e9566f70
commit f814f916a5
2 changed files with 496 additions and 2 deletions
@@ -1,6 +1,6 @@
import unittest
from sqlalchemy import CHAR, BigInteger, CheckConstraint, Integer, String, Table, UniqueConstraint
from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, UniqueConstraint
from config.database import Base
from module_business.entity.do import master_do, operation_do
@@ -228,6 +228,472 @@ EXPECTED_COLUMNS = {
},
}
EXPECTED_COLUMN_TYPES = {
'biz_strain': {
'strain_id': (BigInteger, None),
'strain_code': (String, 64),
'strain_name': (String, 100),
'status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_warehouse': {
'warehouse_id': (BigInteger, None),
'warehouse_code': (String, 64),
'warehouse_name': (String, 100),
'address': (String, 500),
'status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_customer': {
'customer_id': (BigInteger, None),
'customer_code': (String, 64),
'customer_name': (String, 100),
'status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_customer_site': {
'site_id': (BigInteger, None),
'customer_id': (BigInteger, None),
'site_code': (String, 64),
'site_name': (String, 100),
'address': (String, 500),
'status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_production_line': {
'line_id': (BigInteger, None),
'site_id': (BigInteger, None),
'line_code': (String, 64),
'line_name': (String, 100),
'status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_pallet': {
'pallet_id': (BigInteger, None),
'pallet_code': (String, 64),
'qr_token': (String, 128),
'capacity_packages': (Integer, None),
'asset_status': (CHAR, 1),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_user_warehouse': {
'user_id': (BigInteger, None),
'warehouse_id': (BigInteger, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
},
'biz_user_site': {
'user_id': (BigInteger, None),
'site_id': (BigInteger, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
},
'biz_inbound_order': {
'inbound_id': (BigInteger, None),
'inbound_no': (String, 64),
'warehouse_id': (BigInteger, None),
'status': (String, 32),
'confirm_idempotency_key': (String, 64),
'confirm_request_hash': (String, 64),
'confirmed_by': (BigInteger, None),
'confirmed_at': (DateTime, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_inbound_item': {
'inbound_item_id': (BigInteger, None),
'inbound_id': (BigInteger, None),
'pallet_id': (BigInteger, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
},
'biz_filling_record': {
'filling_id': (BigInteger, None),
'filling_no': (String, 64),
'pallet_id': (BigInteger, None),
'warehouse_id': (BigInteger, None),
'strain_id': (BigInteger, None),
'strain_code_snapshot': (String, 64),
'strain_name_snapshot': (String, 100),
'batch_no': (String, 64),
'package_spec': (String, 64),
'initial_packages': (Integer, None),
'active_slot': (String, 16),
'closed_at': (DateTime, None),
'idempotency_key': (String, 64),
'request_hash': (String, 64),
'operator_id': (BigInteger, None),
'operated_at': (DateTime, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_shipment_order': {
'shipment_id': (BigInteger, None),
'shipment_no': (String, 64),
'source_warehouse_id': (BigInteger, None),
'target_site_id': (BigInteger, None),
'status': (String, 32),
'confirm_idempotency_key': (String, 64),
'confirm_request_hash': (String, 64),
'confirmed_by': (BigInteger, None),
'confirmed_at': (DateTime, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_shipment_item': {
'shipment_item_id': (BigInteger, None),
'shipment_id': (BigInteger, None),
'pallet_id': (BigInteger, None),
'active_filling_id': (BigInteger, None),
'package_qty': (Integer, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
},
'biz_usage_record': {
'usage_id': (BigInteger, None),
'usage_no': (String, 64),
'pallet_id': (BigInteger, None),
'active_filling_id': (BigInteger, None),
'site_id': (BigInteger, None),
'line_id': (BigInteger, None),
'used_packages': (Integer, None),
'remaining_packages_after': (Integer, None),
'idempotency_key': (String, 64),
'request_hash': (String, 64),
'operator_id': (BigInteger, None),
'occurred_at': (DateTime, None),
},
'biz_return_order': {
'return_id': (BigInteger, None),
'return_no': (String, 64),
'source_site_id': (BigInteger, None),
'target_warehouse_id': (BigInteger, None),
'status': (String, 32),
'request_idempotency_key': (String, 64),
'request_hash': (String, 64),
'confirm_idempotency_key': (String, 64),
'confirm_request_hash': (String, 64),
'requested_by': (BigInteger, None),
'requested_at': (DateTime, None),
'confirmed_by': (BigInteger, None),
'confirmed_at': (DateTime, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
'update_by': (String, 64),
'update_time': (DateTime, None),
'remark': (String, 500),
},
'biz_return_item': {
'return_item_id': (BigInteger, None),
'return_id': (BigInteger, None),
'pallet_id': (BigInteger, None),
'active_filling_id_snapshot': (BigInteger, None),
'remaining_packages_snapshot': (Integer, None),
'create_by': (String, 64),
'create_time': (DateTime, None),
},
'biz_pallet_inventory': {
'pallet_id': (BigInteger, None),
'active_filling_id': (BigInteger, None),
'warehouse_id': (BigInteger, None),
'site_id': (BigInteger, None),
'current_line_id': (BigInteger, None),
'flow_state': (String, 32),
'remaining_packages': (Integer, None),
'last_event_id': (BigInteger, None),
'version': (Integer, None),
'updated_at': (DateTime, None),
},
'biz_pallet_event': {
'event_id': (BigInteger, None),
'pallet_id': (BigInteger, None),
'event_seq': (Integer, None),
'event_type': (String, 32),
'source_type': (String, 32),
'source_id': (BigInteger, None),
'before_state': (String, 32),
'after_state': (String, 32),
'before_warehouse_id': (BigInteger, None),
'before_site_id': (BigInteger, None),
'before_line_id': (BigInteger, None),
'after_warehouse_id': (BigInteger, None),
'after_site_id': (BigInteger, None),
'after_line_id': (BigInteger, None),
'before_remaining_packages': (Integer, None),
'after_remaining_packages': (Integer, None),
'operator_id': (BigInteger, None),
'occurred_at': (DateTime, None),
'idempotency_key': (String, 64),
'request_hash': (String, 64),
},
}
EXPECTED_NULLABILITY = {
'biz_strain': {
'strain_id': False,
'strain_code': False,
'strain_name': False,
'status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_warehouse': {
'warehouse_id': False,
'warehouse_code': False,
'warehouse_name': False,
'address': True,
'status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_customer': {
'customer_id': False,
'customer_code': False,
'customer_name': False,
'status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_customer_site': {
'site_id': False,
'customer_id': False,
'site_code': False,
'site_name': False,
'address': True,
'status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_production_line': {
'line_id': False,
'site_id': False,
'line_code': False,
'line_name': False,
'status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_pallet': {
'pallet_id': False,
'pallet_code': False,
'qr_token': False,
'capacity_packages': False,
'asset_status': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_user_warehouse': {
'user_id': False,
'warehouse_id': False,
'create_by': True,
'create_time': True,
},
'biz_user_site': {
'user_id': False,
'site_id': False,
'create_by': True,
'create_time': True,
},
'biz_inbound_order': {
'inbound_id': False,
'inbound_no': False,
'warehouse_id': False,
'status': False,
'confirm_idempotency_key': True,
'confirm_request_hash': True,
'confirmed_by': True,
'confirmed_at': True,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_inbound_item': {
'inbound_item_id': False,
'inbound_id': False,
'pallet_id': False,
'create_by': True,
'create_time': True,
},
'biz_filling_record': {
'filling_id': False,
'filling_no': False,
'pallet_id': False,
'warehouse_id': False,
'strain_id': False,
'strain_code_snapshot': False,
'strain_name_snapshot': False,
'batch_no': False,
'package_spec': False,
'initial_packages': False,
'active_slot': True,
'closed_at': True,
'idempotency_key': False,
'request_hash': False,
'operator_id': False,
'operated_at': False,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_shipment_order': {
'shipment_id': False,
'shipment_no': False,
'source_warehouse_id': False,
'target_site_id': False,
'status': False,
'confirm_idempotency_key': True,
'confirm_request_hash': True,
'confirmed_by': True,
'confirmed_at': True,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_shipment_item': {
'shipment_item_id': False,
'shipment_id': False,
'pallet_id': False,
'active_filling_id': True,
'package_qty': True,
'create_by': True,
'create_time': True,
},
'biz_usage_record': {
'usage_id': False,
'usage_no': False,
'pallet_id': False,
'active_filling_id': False,
'site_id': False,
'line_id': False,
'used_packages': False,
'remaining_packages_after': False,
'idempotency_key': False,
'request_hash': False,
'operator_id': False,
'occurred_at': False,
},
'biz_return_order': {
'return_id': False,
'return_no': False,
'source_site_id': False,
'target_warehouse_id': False,
'status': False,
'request_idempotency_key': False,
'request_hash': False,
'confirm_idempotency_key': True,
'confirm_request_hash': True,
'requested_by': False,
'requested_at': False,
'confirmed_by': True,
'confirmed_at': True,
'create_by': True,
'create_time': True,
'update_by': True,
'update_time': True,
'remark': True,
},
'biz_return_item': {
'return_item_id': False,
'return_id': False,
'pallet_id': False,
'active_filling_id_snapshot': True,
'remaining_packages_snapshot': False,
'create_by': True,
'create_time': True,
},
'biz_pallet_inventory': {
'pallet_id': False,
'active_filling_id': True,
'warehouse_id': True,
'site_id': True,
'current_line_id': True,
'flow_state': False,
'remaining_packages': False,
'last_event_id': True,
'version': False,
'updated_at': False,
},
'biz_pallet_event': {
'event_id': False,
'pallet_id': False,
'event_seq': False,
'event_type': False,
'source_type': False,
'source_id': False,
'before_state': False,
'after_state': False,
'before_warehouse_id': True,
'before_site_id': True,
'before_line_id': True,
'after_warehouse_id': True,
'after_site_id': True,
'after_line_id': True,
'before_remaining_packages': False,
'after_remaining_packages': False,
'operator_id': False,
'occurred_at': False,
'idempotency_key': False,
'request_hash': False,
},
}
EXPECTED_PRIMARY_KEYS = {
'biz_strain': ('strain_id',),
'biz_warehouse': ('warehouse_id',),
@@ -436,6 +902,34 @@ class BusinessModelContractTest(unittest.TestCase):
self.assertEqual(table_name, model.__tablename__)
self.assertEqual(EXPECTED_COLUMNS[table_name], set(model.__table__.columns.keys()))
def test_every_column_type_and_string_length_matches_contract(self) -> None:
business_tables = {name for name in Base.metadata.tables if name.startswith('biz_')}
self.assertEqual(business_tables, set(EXPECTED_COLUMN_TYPES))
for table_name, expected_columns in EXPECTED_COLUMN_TYPES.items():
table = Base.metadata.tables[table_name]
with self.subTest(table_name=table_name, contract='all_type_columns'):
self.assertEqual(set(expected_columns), set(table.columns.keys()))
for column_name, (expected_type, expected_length) in expected_columns.items():
column_type = table.c[column_name].type
with self.subTest(table_name=table_name, column_name=column_name):
self.assertIs(expected_type, type(column_type))
self.assertEqual(expected_length, getattr(column_type, 'length', None))
def test_every_column_nullable_flag_matches_contract(self) -> None:
business_tables = {name for name in Base.metadata.tables if name.startswith('biz_')}
self.assertEqual(business_tables, set(EXPECTED_NULLABILITY))
for table_name, expected_columns in EXPECTED_NULLABILITY.items():
table = Base.metadata.tables[table_name]
with self.subTest(table_name=table_name, contract='all_nullable_columns'):
self.assertEqual(set(expected_columns), set(table.columns.keys()))
for column_name, expected_nullable in expected_columns.items():
with self.subTest(table_name=table_name, column_name=column_name):
self.assertIs(expected_nullable, table.c[column_name].nullable)
def test_primary_keys_and_foreign_keys_match_contract(self) -> None:
for table_name, expected_primary_key in EXPECTED_PRIMARY_KEYS.items():
table = Base.metadata.tables[table_name]