from __future__ import annotations import unittest from sqlalchemy import create_engine, select, text from sqlalchemy.orm import Session, sessionmaker import app.models # noqa: E402,F401 from app.models.base import Base # noqa: E402 from app.models.master_data import Warehouse # noqa: E402 from app.models.miniapp import MiniAppPersonAttendancePoint, MiniAppPersonnel, MiniAppPersonRole # noqa: E402 from app.models.operations import WarehouseLocation # noqa: E402 from app.models.org import AiAssistantConfig, Department, Employee, Permission, Role, RolePermission, SystemConfig, User, UserRole # noqa: E402 from app.services.auth import verify_password # noqa: E402 from app.services.system_permissions import MENU_PERMISSION_TREE # noqa: E402 class SystemInitializerSeedTest(unittest.TestCase): def test_table_groups_have_no_duplicates_and_include_expected_tables(self) -> None: from app.services.system_initializer import ( ACCOUNT_RESET_TABLES, BUSINESS_RESET_TABLES, MINIAPP_RESET_TABLES, RESET_TABLES_IN_DELETE_ORDER, SKELETON_TABLES, ) all_tables = BUSINESS_RESET_TABLES + MINIAPP_RESET_TABLES + ACCOUNT_RESET_TABLES + SKELETON_TABLES reset_tables = BUSINESS_RESET_TABLES + MINIAPP_RESET_TABLES + ACCOUNT_RESET_TABLES self.assertEqual(len(all_tables), len(set(all_tables))) self.assertEqual(set(reset_tables).issubset(set(RESET_TABLES_IN_DELETE_ORDER)), True) self.assertEqual(len(RESET_TABLES_IN_DELETE_ORDER), len(set(RESET_TABLES_IN_DELETE_ORDER))) self.assertIn("so_sales_order", BUSINESS_RESET_TABLES) self.assertIn("wh_stock_lot", BUSINESS_RESET_TABLES) self.assertIn("pp_production_batch_ledger", BUSINESS_RESET_TABLES) self.assertIn("production_reports", MINIAPP_RESET_TABLES) self.assertIn("work_sessions", MINIAPP_RESET_TABLES) self.assertIn("sys_user", ACCOUNT_RESET_TABLES) self.assertIn("sys_permission", SKELETON_TABLES) self.assertIn("wh_warehouse", SKELETON_TABLES) class SystemInitializerSkeletonSeedTest(unittest.TestCase): def setUp(self) -> None: engine = create_engine("sqlite+pysqlite:///:memory:", future=True) Base.metadata.create_all(engine) self.SessionLocal = sessionmaker(bind=engine, autoflush=False, autocommit=False, future=True) self.db: Session = self.SessionLocal() def tearDown(self) -> None: self.db.close() def test_seed_system_skeleton_creates_required_defaults(self) -> None: from app.services.system_initializer import SystemInitializeOptions, seed_system_skeleton options = SystemInitializeOptions( mode="reset", company_name="百华", admin_name="超级管理员", admin_phone="13800000000", admin_password="secret123", smart_operation_report_enabled=False, confirm_reset=True, ) result = seed_system_skeleton(self.db, options) self.db.commit() admin_user = self.db.scalar(select(User).where(User.username == "13800000000")) self.assertIsNotNone(admin_user) assert admin_user is not None self.assertEqual(admin_user.is_super_admin, 1) self.assertTrue(verify_password("secret123", admin_user.password_hash)) admin_employee = self.db.scalar(select(Employee).where(Employee.mobile == "13800000000")) self.assertIsNotNone(admin_employee) assert admin_employee is not None self.assertEqual(admin_employee.employee_name, "超级管理员") root = self.db.scalar(select(Department).where(Department.dept_code == "ORG_ROOT")) self.assertIsNotNone(root) assert root is not None self.assertEqual(root.dept_name, "百华") expected_permission_codes = set() def walk(nodes: list[tuple[str, str, list]]) -> None: for code, _name, children in nodes: expected_permission_codes.add(code) walk(children) walk(MENU_PERMISSION_TREE) actual_permission_codes = set(self.db.scalars(select(Permission.permission_code)).all()) self.assertEqual(expected_permission_codes, actual_permission_codes) admin_role = self.db.scalar(select(Role).where(Role.role_code == "ADMIN")) self.assertIsNotNone(admin_role) assert admin_role is not None self.assertEqual( self.db.query(RolePermission).filter(RolePermission.role_id == admin_role.id).count(), len(expected_permission_codes), ) role_names = {role.role_code: role.role_name for role in self.db.scalars(select(Role)).all()} self.assertEqual( role_names, { "ADMIN": "超级管理员", "PURCHASER": "采购专员", "WAREHOUSE": "仓库管理人员", "SALES": "销售人员", }, ) self.assertEqual(self.db.query(UserRole).count(), 1) self.assertEqual(self.db.query(Warehouse).count(), 6) self.assertEqual(self.db.query(WarehouseLocation).count(), 6) self.assertEqual({row.warehouse_type for row in self.db.scalars(select(Warehouse)).all()}, {"RAW", "SEMI", "FINISHED", "AUX", "SCRAP", "RETURN"}) self.assertEqual(self.db.query(WarehouseLocation).filter(WarehouseLocation.is_default == 1).count(), 6) prefix = self.db.scalar(select(SystemConfig).where(SystemConfig.config_code == "RAW_MATERIAL_LOT_PREFIX")) self.assertIsNotNone(prefix) assert prefix is not None self.assertEqual(prefix.config_value, "YL") smart = self.db.scalar(select(SystemConfig).where(SystemConfig.config_code == "SMART_OPERATION_REPORT_ENABLED")) self.assertIsNotNone(smart) assert smart is not None self.assertEqual(smart.config_value, "关闭") ai_config = self.db.scalar(select(AiAssistantConfig)) self.assertIsNotNone(ai_config) assert ai_config is not None self.assertEqual(ai_config.assistant_name, "百华工艺助手") units = dict(self.db.execute(text("SELECT unit_code, unit_name FROM md_unit")).all()) self.assertEqual(units, {"KG": "kg", "PCS": "件", "SET": "套"}) categories = dict(self.db.execute(text("SELECT category_code, category_name FROM md_item_category")).all()) self.assertEqual(categories, {"RAW": "原材料", "SEMI": "半成品", "FINISHED": "成品", "AUX": "辅料", "SCRAP": "废料"}) miniapp_admin = self.db.get(MiniAppPersonnel, "13800000000") self.assertIsNotNone(miniapp_admin) assert miniapp_admin is not None self.assertEqual(miniapp_admin.name, "超级管理员") self.assertIsNotNone(self.db.get(MiniAppPersonRole, {"phone": "13800000000", "role": "admin"})) self.assertIsNotNone( self.db.get( MiniAppPersonAttendancePoint, {"phone": "13800000000", "attendance_point_name": "百华"}, ) ) self.assertEqual(result.seeded["warehouse_count"], 6) self.assertEqual(result.seeded["admin_username"], "13800000000") def test_seed_system_skeleton_defaults_smart_operation_report_to_enabled(self) -> None: from app.services.system_initializer import SystemInitializeOptions, seed_system_skeleton options = SystemInitializeOptions( mode="fresh", company_name="百华", admin_name="超级管理员", admin_phone="13800000000", admin_password="secret123", ) result = seed_system_skeleton(self.db, options) self.db.commit() smart = self.db.scalar(select(SystemConfig).where(SystemConfig.config_code == "SMART_OPERATION_REPORT_ENABLED")) self.assertIsNotNone(smart) assert smart is not None self.assertEqual(smart.config_value, "开启") self.assertEqual(result.seeded["smart_operation_report_enabled"], True) if __name__ == "__main__": unittest.main()