From 7aeed941964bc4f76167d15078327e2ce64c5a99 Mon Sep 17 00:00:00 2001 From: xianze Date: Fri, 5 Jun 2026 16:59:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(compare):=20=E6=AF=94=E4=BB=B7=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E5=88=97=E8=A1=A8=E6=8C=89=E5=BA=97=E5=90=8D=E5=8C=B9?= =?UTF-8?q?=E9=85=8D=E7=9C=9F=E5=AE=9E=E4=B8=8B=E5=8D=95=E6=A0=87=E8=AE=B0?= =?UTF-8?q?=E5=B7=B2=E4=B8=8B=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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) --- app/repositories/comparison.py | 27 ++++++++++++++++++++++++++- app/schemas/compare_record.py | 3 +++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/app/repositories/comparison.py b/app/repositories/comparison.py index 9a164d0..ad362e5 100644 --- a/app/repositories/comparison.py +++ b/app/repositories/comparison.py @@ -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 diff --git a/app/schemas/compare_record.py b/app/schemas/compare_record.py index b7eb0fd..1d2cb22 100644 --- a/app/schemas/compare_record.py +++ b/app/schemas/compare_record.py @@ -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