修复:校正业务模型审计默认值

This commit is contained in:
焦龙言
2026-07-24 20:45:10 +08:00
parent f814f916a5
commit eab725a541
3 changed files with 157 additions and 51 deletions
@@ -30,10 +30,10 @@ class BizStrain(Base):
strain_code = Column(String(64), nullable=False, unique=True, comment='菌种编码') strain_code = Column(String(64), nullable=False, unique=True, comment='菌种编码')
strain_name = Column(String(100), nullable=False, comment='菌种名称') strain_name = Column(String(100), nullable=False, comment='菌种名称')
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)') status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -56,10 +56,10 @@ class BizWarehouse(Base):
warehouse_name = Column(String(100), nullable=False, comment='仓库名称') warehouse_name = Column(String(100), nullable=False, comment='仓库名称')
address = Column(String(500), nullable=True, comment='仓库地址') address = Column(String(500), nullable=True, comment='仓库地址')
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)') status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -81,10 +81,10 @@ class BizCustomer(Base):
customer_code = Column(String(64), nullable=False, unique=True, comment='客户编码') customer_code = Column(String(64), nullable=False, unique=True, comment='客户编码')
customer_name = Column(String(100), nullable=False, comment='客户名称') customer_name = Column(String(100), nullable=False, comment='客户名称')
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)') status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -114,10 +114,10 @@ class BizCustomerSite(Base):
site_name = Column(String(100), nullable=False, comment='现场名称') site_name = Column(String(100), nullable=False, comment='现场名称')
address = Column(String(500), nullable=True, comment='现场地址') address = Column(String(500), nullable=True, comment='现场地址')
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)') status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -146,10 +146,10 @@ class BizProductionLine(Base):
line_code = Column(String(64), nullable=False, comment='产线编码') line_code = Column(String(64), nullable=False, comment='产线编码')
line_name = Column(String(100), nullable=False, comment='产线名称') line_name = Column(String(100), nullable=False, comment='产线名称')
status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)') status = Column(CHAR(1), nullable=False, server_default='0', comment='状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -173,10 +173,10 @@ class BizPallet(Base):
qr_token = Column(String(128), nullable=False, unique=True, comment='二维码固定标识') qr_token = Column(String(128), nullable=False, unique=True, comment='二维码固定标识')
capacity_packages = Column(Integer, nullable=False, comment='容量包数') capacity_packages = Column(Integer, nullable=False, comment='容量包数')
asset_status = Column(CHAR(1), nullable=False, server_default='0', comment='资产状态(0正常 1停用)') asset_status = Column(CHAR(1), nullable=False, server_default='0', comment='资产状态(0正常 1停用)')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -205,8 +205,8 @@ class BizUserWarehouse(Base):
nullable=False, nullable=False,
comment='仓库ID', comment='仓库ID',
) )
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
class BizUserSite(Base): class BizUserSite(Base):
@@ -229,5 +229,5 @@ class BizUserSite(Base):
nullable=False, nullable=False,
comment='现场ID', comment='现场ID',
) )
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
@@ -29,10 +29,10 @@ class BizInboundOrder(Base):
confirm_request_hash = Column(String(64), nullable=True, comment='确认请求摘要') confirm_request_hash = Column(String(64), nullable=True, comment='确认请求摘要')
confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID') confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID')
confirmed_at = Column(DateTime, nullable=True, comment='确认时间') confirmed_at = Column(DateTime, nullable=True, comment='确认时间')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -64,8 +64,8 @@ class BizInboundItem(Base):
comment='入库单ID', comment='入库单ID',
) )
pallet_id = Column(BigInteger, ForeignKey('biz_pallet.pallet_id'), nullable=False, comment='托盘ID') pallet_id = Column(BigInteger, ForeignKey('biz_pallet.pallet_id'), nullable=False, comment='托盘ID')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
class BizFillingRecord(Base): class BizFillingRecord(Base):
@@ -103,10 +103,10 @@ class BizFillingRecord(Base):
request_hash = Column(String(64), nullable=False, comment='请求摘要') request_hash = Column(String(64), nullable=False, comment='请求摘要')
operator_id = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=False, comment='操作人ID') operator_id = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=False, comment='操作人ID')
operated_at = Column(DateTime, nullable=False, comment='操作时间') operated_at = Column(DateTime, nullable=False, comment='操作时间')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -143,10 +143,10 @@ class BizShipmentOrder(Base):
confirm_request_hash = Column(String(64), nullable=True, comment='确认请求摘要') confirm_request_hash = Column(String(64), nullable=True, comment='确认请求摘要')
confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID') confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID')
confirmed_at = Column(DateTime, nullable=True, comment='确认时间') confirmed_at = Column(DateTime, nullable=True, comment='确认时间')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -189,8 +189,8 @@ class BizShipmentItem(Base):
comment='确认时活动装填记录ID', comment='确认时活动装填记录ID',
) )
package_qty = Column(Integer, nullable=True, comment='确认时包数快照') package_qty = Column(Integer, nullable=True, comment='确认时包数快照')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
class BizUsageRecord(Base): class BizUsageRecord(Base):
@@ -257,10 +257,10 @@ class BizReturnOrder(Base):
requested_at = Column(DateTime, nullable=False, comment='申请时间') requested_at = Column(DateTime, nullable=False, comment='申请时间')
confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID') confirmed_by = Column(BigInteger, ForeignKey('sys_user.user_id'), nullable=True, comment='确认人ID')
confirmed_at = Column(DateTime, nullable=True, comment='确认时间') confirmed_at = Column(DateTime, nullable=True, comment='确认时间')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
update_by = Column(String(64), nullable=True, server_default="''", comment='更新者') update_by = Column(String(64), nullable=True, server_default='', comment='更新者')
update_time = Column(DateTime, nullable=True, default=datetime.now(), comment='更新时间') update_time = Column(DateTime, nullable=True, default=datetime.now, comment='更新时间')
remark = Column( remark = Column(
String(500), String(500),
nullable=True, nullable=True,
@@ -303,8 +303,8 @@ class BizReturnItem(Base):
comment='申请时活动装填记录快照', comment='申请时活动装填记录快照',
) )
remaining_packages_snapshot = Column(Integer, nullable=False, comment='申请时剩余包数快照') remaining_packages_snapshot = Column(Integer, nullable=False, comment='申请时剩余包数快照')
create_by = Column(String(64), nullable=True, server_default="''", comment='创建者') create_by = Column(String(64), nullable=True, server_default='', comment='创建者')
create_time = Column(DateTime, nullable=True, default=datetime.now(), comment='创建时间') create_time = Column(DateTime, nullable=True, default=datetime.now, comment='创建时间')
class BizPalletInventory(Base): class BizPalletInventory(Base):
@@ -367,7 +367,7 @@ class BizPalletInventory(Base):
comment='最后事件ID', comment='最后事件ID',
) )
version = Column(Integer, nullable=False, server_default='0', comment='并发版本号') version = Column(Integer, nullable=False, server_default='0', comment='并发版本号')
updated_at = Column(DateTime, nullable=False, default=datetime.now(), comment='更新时间') updated_at = Column(DateTime, nullable=False, default=datetime.now, comment='更新时间')
class BizPalletEvent(Base): class BizPalletEvent(Base):
@@ -1,6 +1,8 @@
import unittest import unittest
from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, UniqueConstraint from sqlalchemy import CHAR, BigInteger, CheckConstraint, DateTime, Integer, String, Table, UniqueConstraint
from sqlalchemy.dialects import mysql, postgresql
from sqlalchemy.schema import CreateColumn
from config.database import Base from config.database import Base
from module_business.entity.do import master_do, operation_do from module_business.entity.do import master_do, operation_do
@@ -694,6 +696,63 @@ EXPECTED_NULLABILITY = {
}, },
} }
EXPECTED_CALLABLE_DATETIME_DEFAULTS = {
('biz_strain', 'create_time'),
('biz_strain', 'update_time'),
('biz_warehouse', 'create_time'),
('biz_warehouse', 'update_time'),
('biz_customer', 'create_time'),
('biz_customer', 'update_time'),
('biz_customer_site', 'create_time'),
('biz_customer_site', 'update_time'),
('biz_production_line', 'create_time'),
('biz_production_line', 'update_time'),
('biz_pallet', 'create_time'),
('biz_pallet', 'update_time'),
('biz_user_warehouse', 'create_time'),
('biz_user_site', 'create_time'),
('biz_inbound_order', 'create_time'),
('biz_inbound_order', 'update_time'),
('biz_inbound_item', 'create_time'),
('biz_filling_record', 'create_time'),
('biz_filling_record', 'update_time'),
('biz_shipment_order', 'create_time'),
('biz_shipment_order', 'update_time'),
('biz_shipment_item', 'create_time'),
('biz_return_order', 'create_time'),
('biz_return_order', 'update_time'),
('biz_return_item', 'create_time'),
('biz_pallet_inventory', 'updated_at'),
}
EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS = {
('biz_strain', 'create_by'),
('biz_strain', 'update_by'),
('biz_warehouse', 'create_by'),
('biz_warehouse', 'update_by'),
('biz_customer', 'create_by'),
('biz_customer', 'update_by'),
('biz_customer_site', 'create_by'),
('biz_customer_site', 'update_by'),
('biz_production_line', 'create_by'),
('biz_production_line', 'update_by'),
('biz_pallet', 'create_by'),
('biz_pallet', 'update_by'),
('biz_user_warehouse', 'create_by'),
('biz_user_site', 'create_by'),
('biz_inbound_order', 'create_by'),
('biz_inbound_order', 'update_by'),
('biz_inbound_item', 'create_by'),
('biz_filling_record', 'create_by'),
('biz_filling_record', 'update_by'),
('biz_shipment_order', 'create_by'),
('biz_shipment_order', 'update_by'),
('biz_shipment_item', 'create_by'),
('biz_return_order', 'create_by'),
('biz_return_order', 'update_by'),
('biz_return_item', 'create_by'),
}
EXPECTED_PRIMARY_KEYS = { EXPECTED_PRIMARY_KEYS = {
'biz_strain': ('strain_id',), 'biz_strain': ('strain_id',),
'biz_warehouse': ('warehouse_id',), 'biz_warehouse': ('warehouse_id',),
@@ -930,6 +989,53 @@ class BusinessModelContractTest(unittest.TestCase):
with self.subTest(table_name=table_name, column_name=column_name): with self.subTest(table_name=table_name, column_name=column_name):
self.assertIs(expected_nullable, table.c[column_name].nullable) self.assertIs(expected_nullable, table.c[column_name].nullable)
def test_datetime_python_defaults_are_callable(self) -> None:
business_tables = [table for table in Base.metadata.tables.values() if table.name.startswith('biz_')]
actual_defaults = {
(table.name, column.name)
for table in business_tables
for column in table.columns
if type(column.type) is DateTime and column.default is not None
}
self.assertEqual(EXPECTED_CALLABLE_DATETIME_DEFAULTS, actual_defaults)
violations = []
for table_name, column_name in sorted(EXPECTED_CALLABLE_DATETIME_DEFAULTS):
column_default = Base.metadata.tables[table_name].c[column_name].default
if column_default is None or not column_default.is_callable or column_default.is_scalar:
violations.append(
(
table_name,
column_name,
None if column_default is None else column_default.is_callable,
None if column_default is None else column_default.is_scalar,
)
)
self.assertEqual([], violations)
def test_audit_user_server_defaults_compile_to_empty_strings(self) -> None:
business_tables = [table for table in Base.metadata.tables.values() if table.name.startswith('biz_')]
actual_audit_columns = {
(table.name, column.name)
for table in business_tables
for column in table.columns
if column.name in {'create_by', 'update_by'}
}
self.assertEqual(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS, actual_audit_columns)
violations = []
dialects = {'mysql': mysql.dialect(), 'postgresql': postgresql.dialect()}
for table_name, column_name in sorted(EXPECTED_EMPTY_AUDIT_SERVER_DEFAULTS):
column = Base.metadata.tables[table_name].c[column_name]
for dialect_name, dialect in dialects.items():
compiled_column = str(CreateColumn(column).compile(dialect=dialect))
_, separator, compiled_default = compiled_column.partition(' DEFAULT ')
if separator:
compiled_default = compiled_default.split(' COMMENT ', maxsplit=1)[0].strip()
if compiled_default != "''":
violations.append((dialect_name, table_name, column_name, compiled_default))
self.assertEqual([], violations)
def test_primary_keys_and_foreign_keys_match_contract(self) -> None: def test_primary_keys_and_foreign_keys_match_contract(self) -> None:
for table_name, expected_primary_key in EXPECTED_PRIMARY_KEYS.items(): for table_name, expected_primary_key in EXPECTED_PRIMARY_KEYS.items():
table = Base.metadata.tables[table_name] table = Base.metadata.tables[table_name]