90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
"""市場情報平台種子資料寫入 dry-run 規劃。
|
||
|
||
本模組只建立 upsert preview 與 schema smoke 結果,不執行資料庫寫入。
|
||
"""
|
||
|
||
import json
|
||
|
||
from database.manager import Base
|
||
|
||
|
||
MARKET_PLATFORM_REQUIRED_COLUMNS = (
|
||
"code",
|
||
"name",
|
||
"base_url",
|
||
"enabled",
|
||
"crawl_policy_json",
|
||
)
|
||
|
||
|
||
def build_schema_smoke(expected_tables, metadata=None):
|
||
"""檢查 ORM metadata 是否具備 market_* 表與 platform upsert 必要欄位。"""
|
||
metadata = metadata or Base.metadata
|
||
metadata_tables = metadata.tables
|
||
table_names = set(metadata_tables)
|
||
missing_tables = [
|
||
table_name for table_name in expected_tables
|
||
if table_name not in table_names
|
||
]
|
||
market_platform = metadata_tables.get("market_platforms")
|
||
platform_columns = (
|
||
set(market_platform.columns.keys())
|
||
if market_platform is not None
|
||
else set()
|
||
)
|
||
missing_platform_columns = [
|
||
column_name for column_name in MARKET_PLATFORM_REQUIRED_COLUMNS
|
||
if column_name not in platform_columns
|
||
]
|
||
|
||
return {
|
||
"passed": not missing_tables and not missing_platform_columns,
|
||
"expected_table_count": len(expected_tables),
|
||
"metadata_table_count": len(table_names),
|
||
"missing_tables": missing_tables,
|
||
"market_platform_required_columns": list(MARKET_PLATFORM_REQUIRED_COLUMNS),
|
||
"missing_market_platform_columns": missing_platform_columns,
|
||
}
|
||
|
||
|
||
def build_platform_seed_writer_plan(seed_plan, write_guard, schema_smoke):
|
||
"""建立 market_platforms upsert dry-run plan,不建立 session、不 commit。"""
|
||
operations = []
|
||
for seed in seed_plan.get("seeds", []):
|
||
operations.append(
|
||
{
|
||
"operation": "upsert",
|
||
"table": "market_platforms",
|
||
"lookup": {"code": seed["code"]},
|
||
"values": {
|
||
"code": seed["code"],
|
||
"name": seed["name"],
|
||
"base_url": seed["base_url"],
|
||
"enabled": False,
|
||
"crawl_policy_json": json.dumps(
|
||
seed["crawl_policy_json"],
|
||
ensure_ascii=False,
|
||
sort_keys=True,
|
||
),
|
||
},
|
||
"sql_shape": (
|
||
"INSERT INTO market_platforms (...) VALUES (...) "
|
||
"ON CONFLICT(code) DO UPDATE SET ..."
|
||
),
|
||
"write_status": "blocked_dry_run_only",
|
||
}
|
||
)
|
||
|
||
return {
|
||
"mode": "dry_run",
|
||
"operation_count": len(operations),
|
||
"operations": operations,
|
||
"schema_smoke": schema_smoke,
|
||
"ready_to_write": False,
|
||
"writes_executed": False,
|
||
"would_write_database": False,
|
||
"database_write_allowed": bool(write_guard.get("database_write_allowed")),
|
||
"blocked_reasons": write_guard.get("blocked_reasons", []),
|
||
"write_action": "preview_only_no_session_no_commit",
|
||
}
|