4506677483
Co-authored-by: xianze <ze@192.168.0.138> Reviewed-on: #13 Co-authored-by: zhangxianze <zhangxianze@wonderable.ai> Co-committed-by: zhangxianze <zhangxianze@wonderable.ai>
68 lines
3.2 KiB
Python
68 lines
3.2 KiB
Python
"""上报更低价记录表(price_report)。
|
|
|
|
用户在「比价记录」里选一条记录,上报「某平台有比我们算出的最低价更低的价格」,带截图证明,
|
|
人工审核通过奖励金币。与 feedback(自由文本反馈)不同:本表结构化——关联具体比价记录、
|
|
原最低价 vs 上报价、审核状态、奖励。
|
|
|
|
- 原最低价快照(original_*)由后端按 comparison_record_id 反查比价记录的 best_* 冗余填入,
|
|
避免被关联记录后续删/改后对不上。
|
|
- 价格统一存「分」(cents),与 comparison_record / savings_record 一致。
|
|
- status: pending(审核中)/ approved(已通过)/ rejected(未通过),对齐前端筛选与状态徽标。
|
|
- images: 截图相对 URL 列表(/media/price_report/...,复用 app.core.media)。
|
|
- 奖励发放(通过 → 钱包 +reward_coins)是人工审核后台动作,提交时一律 pending,本表只留字段。
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import JSON, DateTime, ForeignKey, Integer, String, func
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.db.base import Base
|
|
|
|
|
|
class PriceReport(Base):
|
|
__tablename__ = "price_report"
|
|
|
|
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
|
user_id: Mapped[int] = mapped_column(
|
|
Integer, ForeignKey("user.id"), index=True, nullable=False
|
|
)
|
|
# 选中的那条比价记录(可空:记录被删后仍保留上报历史)
|
|
comparison_record_id: Mapped[int | None] = mapped_column(
|
|
Integer, ForeignKey("comparison_record.id"), index=True, nullable=True
|
|
)
|
|
|
|
# ===== 选中比价记录的快照(后端反查 comparison_record 填入,冗余存) =====
|
|
store_name: Mapped[str | None] = mapped_column(String(128), nullable=True)
|
|
dish_summary: Mapped[str | None] = mapped_column(String(256), nullable=True)
|
|
original_platform_id: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
original_platform_name: Mapped[str | None] = mapped_column(String(32), nullable=True)
|
|
original_price_cents: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
|
|
# ===== 用户上报的更低价 =====
|
|
reported_platform_id: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
reported_platform_name: Mapped[str] = mapped_column(String(32), nullable=False)
|
|
reported_price_cents: Mapped[int] = mapped_column(Integer, nullable=False)
|
|
# 截图证明 URL 列表(相对路径,如 ["/media/price_report/u1_ab.jpg"])
|
|
images: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
|
|
# ===== 审核(人工后台) =====
|
|
status: Mapped[str] = mapped_column(
|
|
String(16), nullable=False, default="pending", index=True
|
|
)
|
|
reject_reason: Mapped[str | None] = mapped_column(String(256), nullable=True)
|
|
reward_coins: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
|
reviewed_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True), nullable=True
|
|
)
|
|
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True), server_default=func.now(), index=True, nullable=False
|
|
)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover
|
|
return (
|
|
f"<PriceReport id={self.id} user_id={self.user_id} status={self.status}>"
|
|
)
|