Files
shaguabijia-app-server/scripts/seed_push_admin_test.py
T
Ghost 0717c09721 基于 main 接入各厂商直推服务端 (#118)
改动:新增厂商推送配置、设备 push_vendor/push_token 字段、device push-test 接口、心跳超时厂商直推发送逻辑和对应测试。

验证:python -m pytest tests/test_device_push.py tests/test_auth.py tests/test_health.py 通过。

---------

Co-authored-by: guke <guke@wonderable.ai>
Co-authored-by: 左辰勇 <exinglang@gmail.com>
Co-authored-by: lowmaster-chen <1119780489@qq.com>
Reviewed-on: #118
Co-authored-by: Ghost <>
Co-committed-by: Ghost <>
2026-07-22 15:42:25 +08:00

136 lines
6.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""给指定用户(默认 11111111111)造「后台可驱动」的推送联调数据。
覆盖能从**管理后台点一下就触发手机推送**的 3 类事件,每类 10 条待审记录:
事件(PRD #) 后台动作 造的数据
────────────────────────────────────────────────────────────────────
#10 反馈奖励 反馈工单 → 采纳(填回复留言 + 金币) 10 条 pending feedback(标「请采纳」)
#9 官方回复 反馈工单 → 拒绝(填未采纳原因/留言) 10 条 pending feedback(标「请拒绝」)
#11 爆料审核通过 上报更低价 → 通过 10 条 pending price_report
触发链路:admin 审核 → 发金币/改状态 → services/notification_events 落站内消息 + 厂商直推
→ 该用户已注册设备(device_liveness)收到 push。
其余 3 类(#3 提现成功 / #4 提现失败 / #12 好友下单到账)后台无法在本环境驱动
(wxpay 未配 / 提现单唯一约束 / 后台无入口),用 scripts/fire_push_events.py 直接触发。
幂等:每次先删掉本脚本上一轮造的记录(按内容标记 [PUSH测试] 识别,不动用户真实反馈/爆料),再重建。
.venv\\Scripts\\python.exe scripts\\seed_push_admin_test.py
.venv\\Scripts\\python.exe scripts\\seed_push_admin_test.py --phone 11111111111 --count 10
.venv\\Scripts\\python.exe scripts\\seed_push_admin_test.py --clean-only
"""
from __future__ import annotations
import argparse
import logging
import sys
from sqlalchemy import delete, select
from app.db.session import SessionLocal
from app.models.feedback import Feedback
from app.models.price_report import PriceReport
from app.repositories import user as user_repo
logging.getLogger("sqlalchemy.engine").setLevel(logging.WARNING) # 静音 SQL 回显,输出更干净
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
DEFAULT_PHONE = "11111111111"
MARK = "[PUSH测试]" # 本脚本造的数据统一带此标记,幂等清理按它识别(不误删真实数据)
def clean(db, uid: int) -> tuple[int, int]:
"""删掉本脚本上一轮造的带标记记录(任何状态都删,彻底重置)。返回 (删反馈数, 删爆料数)。"""
fb_ids = list(db.execute(
select(Feedback.id).where(Feedback.user_id == uid, Feedback.content.like(f"{MARK}%"))
).scalars())
rep_ids = list(db.execute(
select(PriceReport.id).where(
PriceReport.user_id == uid, PriceReport.store_name.like(f"{MARK}%")
)
).scalars())
if fb_ids:
db.execute(delete(Feedback).where(Feedback.id.in_(fb_ids)))
if rep_ids:
db.execute(delete(PriceReport).where(PriceReport.id.in_(rep_ids)))
db.commit()
return len(fb_ids), len(rep_ids)
def seed(db, uid: int, count: int) -> None:
# #10 反馈奖励:采纳这些 → 手机收「反馈奖励已到账」。采纳时记得在后台填「给用户的回复留言」
# (PRD 要求发奖必带官方留言),否则通知里不带留言行。
for i in range(1, count + 1):
db.add(Feedback(
user_id=uid,
content=f"{MARK} 请【采纳】我 → 触发 #10 反馈奖励推送。测试反馈内容 {i:02d}:比价页能加个历史记录就好了。",
contact="",
source="profile",
status="pending",
))
# #9 官方回复:拒绝这些 → 手机收「您的反馈有回复啦」。拒绝时填「未采纳原因」+「回复留言」。
for i in range(1, count + 1):
db.add(Feedback(
user_id=uid,
content=f"{MARK} 请【拒绝】我 → 触发 #9 官方回复推送。测试反馈内容 {i:02d}:希望支持某某小众平台比价。",
contact="",
source="comparison",
scene="other",
status="pending",
))
# #11 爆料审核通过:通过这些 → 手机收「爆料审核通过」(发固定金币)。
for i in range(1, count + 1):
db.add(PriceReport(
user_id=uid,
comparison_record_id=None,
store_name=f"{MARK}测试火锅店{i:02d}",
dish_summary="招牌套餐 × 1",
original_platform_id="meituan-waimai",
original_platform_name="美团外卖",
original_price_cents=9900,
reported_platform_id="jd-waimai",
reported_platform_name="京东外卖",
reported_price_cents=8800,
images=[],
status="pending",
))
db.commit()
def main() -> None:
parser = argparse.ArgumentParser(description="造后台可驱动的推送联调数据(反馈×2 + 爆料)")
parser.add_argument("--phone", default=DEFAULT_PHONE, help=f"目标用户手机号(默认 {DEFAULT_PHONE})")
parser.add_argument("--count", type=int, default=10, help="每类造多少条(默认 10)")
parser.add_argument("--clean-only", action="store_true", help="只清理本脚本造的数据,不重建")
args = parser.parse_args()
db = SessionLocal()
try:
user = user_repo.get_user_by_phone(db, args.phone)
if user is None:
print(f"❌ 用户 {args.phone} 不存在。请先用该手机号在 App 登录一次再跑本脚本。")
return
uid = user.id
nf, nr = clean(db, uid)
print(f"🧹 已清理上一轮 [PUSH测试] 数据:反馈 {nf} 条、爆料 {nr}")
if args.clean_only:
print("✅ 仅清理,已完成。")
return
seed(db, uid, args.count)
print(f"\n✅ 已为 {args.phone}(id={uid})造好后台联调数据(每类 {args.count} 条):")
print(f" • 反馈工单「请采纳」× {args.count} → 后台【采纳】(填回复留言+金币)→ 手机收 #10 反馈奖励")
print(f" • 反馈工单「请拒绝」× {args.count} → 后台【拒绝】(填未采纳原因/留言)→ 手机收 #9 官方回复")
print(f" • 上报更低价 × {args.count} → 后台【通过】→ 手机收 #11 爆料审核通过")
print("\n👉 打开管理后台(:8771)对应列表即可看到这些待审记录,逐条审核就会推到手机。")
print(" #3/#4/#12 本环境后台驱动不了,用:.venv\\Scripts\\python.exe scripts\\fire_push_events.py")
finally:
db.close()
if __name__ == "__main__":
main()