PMFlow/backend/tests/test_feedback_center_migrat...

101 lines
3.8 KiB
Python

import importlib.util
from pathlib import Path
import sqlalchemy as sa
def _load_migration_module():
path = (
Path(__file__).resolve().parents[1]
/ "alembic"
/ "versions"
/ "20260326_create_feedback_center_tables.py"
)
spec = importlib.util.spec_from_file_location("feedback_center_migration", path)
module = importlib.util.module_from_spec(spec)
assert spec is not None
assert spec.loader is not None
spec.loader.exec_module(module)
return module
def _feedback_center_records_table(metadata: sa.MetaData) -> sa.Table:
return sa.Table(
"feedback_center_records",
metadata,
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
sa.Column("tenant_id", sa.BigInteger(), nullable=False),
sa.Column("project_id", sa.BigInteger(), nullable=True),
sa.Column("source_type", sa.VARCHAR(length=32), nullable=False),
sa.Column("source_id", sa.BigInteger(), nullable=False),
sa.Column("object_type", sa.VARCHAR(length=32), nullable=False),
sa.Column("object_id", sa.BigInteger(), nullable=False),
sa.Column("field_name", sa.VARCHAR(length=128), nullable=False),
sa.Column("before_value", sa.JSON(), nullable=True),
sa.Column("after_value", sa.JSON(), nullable=True),
sa.Column("ai_snapshot", sa.JSON(), nullable=True),
sa.Column("ai_confidence", sa.Float(), nullable=True),
sa.Column("reason_candidates", sa.JSON(), nullable=True),
sa.Column("reason_code", sa.VARCHAR(length=64), nullable=True),
sa.Column("reason_text", sa.Text(), nullable=True),
sa.Column("review_status", sa.VARCHAR(length=16), nullable=False),
sa.Column("reviewed_by", sa.BigInteger(), nullable=True),
sa.Column("reviewed_at", sa.TIMESTAMP(), nullable=True),
sa.Column("source_title", sa.VARCHAR(length=500), nullable=True),
sa.Column("object_title", sa.VARCHAR(length=500), nullable=True),
sa.Column("auto_assigned", sa.Boolean(), nullable=False),
)
def test_insert_record_accepts_json_payloads_for_feedback_center_backfill() -> None:
migration = _load_migration_module()
metadata = sa.MetaData()
table = _feedback_center_records_table(metadata)
engine = sa.create_engine("sqlite:///:memory:")
metadata.create_all(engine)
payload = {
"tenant_id": 1,
"project_id": None,
"source_type": "qa_feedback",
"source_id": 118,
"object_type": "qa_record",
"object_id": 230,
"field_name": "qa_feedback",
"before_value": {"answer": "stub answer"},
"after_value": {"rating": "positive", "helpfulness": "fully"},
"ai_snapshot": {"question": "what happened", "answer": "stub answer"},
"ai_confidence": None,
"reason_candidates": [
{
"code": "answer_incorrect",
"label": "答案不准确",
"description": "AI 输出与业务事实不一致",
}
],
"reason_code": "answer_incorrect",
"reason_text": None,
"review_status": "reviewed",
"reviewed_by": 2,
"reviewed_at": None,
"source_title": "what happened",
"object_title": "what happened",
"auto_assigned": False,
}
with engine.begin() as conn:
migration._insert_record(conn, payload)
row = conn.execute(
sa.select(
table.c.before_value,
table.c.after_value,
table.c.ai_snapshot,
table.c.reason_candidates,
)
).mappings().one()
assert row["before_value"] == payload["before_value"]
assert row["after_value"] == payload["after_value"]
assert row["ai_snapshot"] == payload["ai_snapshot"]
assert row["reason_candidates"] == payload["reason_candidates"]