fix(km): normalize legacy timestamps
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m13s
CD Pipeline / build-and-deploy (push) Successful in 5m41s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 1m13s
CD Pipeline / build-and-deploy (push) Successful in 5m41s
CD Pipeline / post-deploy-checks (push) Has been cancelled
This commit is contained in:
@@ -27,6 +27,7 @@ from src.models.knowledge import (
|
||||
KnowledgeEntry,
|
||||
KnowledgeEntryCreate,
|
||||
)
|
||||
from src.utils.timezone import now_taipei
|
||||
|
||||
logger = structlog.get_logger(__name__)
|
||||
|
||||
@@ -199,6 +200,13 @@ def _normalize_tags(value: object) -> list[str]:
|
||||
return [str(value).strip()] if str(value).strip() else []
|
||||
|
||||
|
||||
def _normalize_int(value: object, *, fallback: int = 0) -> int:
|
||||
try:
|
||||
return int(value or fallback)
|
||||
except (TypeError, ValueError):
|
||||
return fallback
|
||||
|
||||
|
||||
def _normalized_category_expr():
|
||||
return func.coalesce(
|
||||
func.nullif(func.trim(KnowledgeEntryRecord.category), ""),
|
||||
@@ -612,10 +620,10 @@ class KnowledgeDBRepository:
|
||||
# P1-1 M3 2026-04-28 ogt + Claude Sonnet 4.6: 冪等 key
|
||||
path_type=get("path_type"),
|
||||
symptoms_hash=get("symptoms_hash"),
|
||||
view_count=int(get("view_count") or 0),
|
||||
view_count=_normalize_int(get("view_count")),
|
||||
created_by=get("created_by"),
|
||||
created_at=get("created_at"),
|
||||
updated_at=get("updated_at"),
|
||||
created_at=get("created_at") or now_taipei(),
|
||||
updated_at=get("updated_at") or get("created_at") or now_taipei(),
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -86,10 +86,21 @@ def test_knowledge_read_model_normalizes_legacy_tag_shapes_and_null_counts() ->
|
||||
|
||||
json_tag_entry = repo._to_model(_record(tags='["telegram", " ai_loop "]', view_count=None))
|
||||
scalar_tag_entry = repo._to_model(_record(tags="telegram"))
|
||||
bad_count_entry = repo._to_model(_record(view_count="not-a-number"))
|
||||
|
||||
assert json_tag_entry.tags == ["telegram", "ai_loop"]
|
||||
assert json_tag_entry.view_count == 0
|
||||
assert scalar_tag_entry.tags == ["telegram"]
|
||||
assert bad_count_entry.view_count == 0
|
||||
|
||||
|
||||
def test_knowledge_read_model_fills_missing_legacy_timestamps() -> None:
|
||||
repo = KnowledgeDBRepository(db=object()) # type: ignore[arg-type]
|
||||
|
||||
entry = repo._to_model(_record(created_at=None, updated_at=None))
|
||||
|
||||
assert entry.created_at is not None
|
||||
assert entry.updated_at is not None
|
||||
|
||||
|
||||
def test_knowledge_read_model_defaults_null_or_blank_category() -> None:
|
||||
|
||||
Reference in New Issue
Block a user