from __future__ import annotations from pathlib import Path from sqlalchemy import create_engine, inspect import app.models # noqa: F401 from app.models.base import Base MINIAPP_TABLES = { "attendance_points", "personnel", "person_roles", "person_attendance_points", "products", "equipment", "work_schedules", "work_sessions", "work_session_devices", "production_reports", "production_report_items", "report_audit_logs", "mold_lock_feedbacks", "device_qrcodes", "device_qrcode_batch_tasks", "notices", "notice_points", "reconciliation_ledger_entries", } REQUIRED_ERP_TABLES = { "sys_department", "hr_employee", "sys_role", "sys_permission", "sys_role_permission", "sys_user", "sys_user_role", "sys_system_config", "sys_ai_assistant_config", "md_unit", "md_item_category", "md_item", "md_material", "md_product", "md_bom", "md_bom_item", "wh_warehouse", "wh_location", "wh_stock_lot", "wh_stock_balance", "wh_inventory_txn", "pp_material_issue", "pp_material_issue_item", "pp_production_batch_ledger", "pp_production_batch_ledger_txn", "document_archives", } def _erp_model_table_names() -> set[str]: models_dir = Path(__file__).resolve().parents[1] / "app" / "models" table_names: set[str] = set() for model_file in models_dir.glob("*.py"): if model_file.name in {"__init__.py", "base.py", "miniapp.py"}: continue for line in model_file.read_text(encoding="utf-8").splitlines(): stripped = line.strip() if stripped.startswith("__tablename__"): table_names.add(stripped.split("=", 1)[1].strip().strip("\"'")) return table_names def test_app_models_registers_erp_and_miniapp_tables() -> None: expected_tables = _erp_model_table_names() | REQUIRED_ERP_TABLES | MINIAPP_TABLES missing_tables = expected_tables - set(Base.metadata.tables) assert missing_tables == set() def test_reset_table_groups_are_registered_in_metadata() -> None: from app.services.system_initializer import ACCOUNT_RESET_TABLES, BUSINESS_RESET_TABLES, MINIAPP_RESET_TABLES, SKELETON_TABLES expected_tables = set(BUSINESS_RESET_TABLES) | set(MINIAPP_RESET_TABLES) | set(ACCOUNT_RESET_TABLES) | set(SKELETON_TABLES) assert expected_tables.issubset(set(Base.metadata.tables)) def test_registered_models_create_all_in_sqlite_memory() -> None: engine = create_engine("sqlite:///:memory:") Base.metadata.create_all(engine) created_tables = set(inspect(engine).get_table_names()) assert (MINIAPP_TABLES | REQUIRED_ERP_TABLES).issubset(created_tables)