feat(compare): 比价记录列表按店名匹配真实下单标记已下单
list_records 查出本页后,按 store_name 命中该用户 source='compare' 的 savings_record.shop_name 集合算出 ordered(店级、瞬态属性,不加列不迁移); ComparisonRecordOut 加 ordered 字段(from_attributes 读出,缺省 false)。 下单上报不带 trace_id,只能按店名对齐(两边店名同源:比价意图识别的门店名)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,6 +9,7 @@ from sqlalchemy import func, select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.comparison import ComparisonRecord
|
||||
from app.models.savings import SavingsRecord
|
||||
from app.schemas.compare_record import ComparisonRecordIn
|
||||
|
||||
|
||||
@@ -110,6 +111,23 @@ def upsert_record(
|
||||
return rec
|
||||
|
||||
|
||||
def _ordered_shop_names(db: Session, user_id: int) -> set[str]:
|
||||
"""该用户「真实下单」(source='compare')覆盖到的店名集合,用来给比价记录打「已下单」。
|
||||
|
||||
只认 compare(归因命中后真实上报),demo 演示数据不算。下单上报不带 trace_id,
|
||||
只能按店名对齐——两边店名同源(都来自比价意图识别阶段的门店名 query),精确相等即视为同店。
|
||||
语义=店级:同一家店比价过多次,这些记录会一并标「已下单」。
|
||||
"""
|
||||
rows = db.execute(
|
||||
select(SavingsRecord.shop_name).where(
|
||||
SavingsRecord.user_id == user_id,
|
||||
SavingsRecord.source == "compare",
|
||||
SavingsRecord.shop_name.is_not(None),
|
||||
)
|
||||
).scalars().all()
|
||||
return {s for s in rows if s}
|
||||
|
||||
|
||||
def list_records(
|
||||
db: Session,
|
||||
user_id: int,
|
||||
@@ -117,7 +135,7 @@ def list_records(
|
||||
limit: int = 20,
|
||||
cursor: int | None = None,
|
||||
) -> tuple[list[ComparisonRecord], int | None]:
|
||||
"""比价记录分页(按 id 倒序,游标式)。"""
|
||||
"""比价记录分页(按 id 倒序,游标式)。附「已下单」店级标记(瞬态,不写库)。"""
|
||||
stmt = select(ComparisonRecord).where(ComparisonRecord.user_id == user_id)
|
||||
if cursor is not None:
|
||||
stmt = stmt.where(ComparisonRecord.id < cursor)
|
||||
@@ -125,6 +143,13 @@ def list_records(
|
||||
|
||||
items = list(db.execute(stmt).scalars().all())
|
||||
next_cursor = items[-1].id if len(items) == limit else None
|
||||
|
||||
# 「已下单」标记:本页记录的 store_name 若落在该用户真实下单的店名集合里即 True。
|
||||
# ordered 非 ORM 列,仅挂实例上供 ComparisonRecordOut(from_attributes) 读出,不持久化。
|
||||
ordered_shops = _ordered_shop_names(db, user_id)
|
||||
for it in items:
|
||||
it.ordered = bool(it.store_name and it.store_name in ordered_shops)
|
||||
|
||||
return items, next_cursor
|
||||
|
||||
|
||||
|
||||
@@ -94,6 +94,9 @@ class ComparisonRecordOut(BaseModel):
|
||||
items: list = []
|
||||
comparison_results: list = []
|
||||
skipped_dish_names: list = []
|
||||
# 「已下单」(店级):该店名在该用户真实下单(source='compare')里出现过即 True。
|
||||
# 由 list_records 动态算出挂在 ORM 实例上(非 DB 列),from_attributes 读出;缺省 False。
|
||||
ordered: bool = False
|
||||
created_at: datetime
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user