# Backend Phase Report — 交易与会员闭环

项目路径：/data/sme-omnistore-p0-remediated-20260509/backend
服务器：192.168.50.139:22022
时间：2026-05-09

---

## 修改的文件

### 1. app/api/routers/store/orders.py — 优惠券 used_count 未更新 ✅ 已修复

问题：create_order 中使用了优惠券但从未 commit 更新 used_count，
导致优惠券总量限制形同虚设，可被无限重复使用。

修复：
- 新增 import: from app.core.models.discount import Discount
- 在 calculate_pricing 之后，新增 coupon 对象查询（行 132-141）
- 在 await db.commit() 之前，新增 coupon_obj.used_count += 1（行 217-218）

代码：
    # 2b. 获取优惠券对象（用于后续 used_count 更新）
    coupon_obj = None
    if body.coupon_code:
        cr = await db.execute(
            select(Discount).where(
                Discount.tenant_id == tenant_id,
                Discount.code == body.coupon_code,
            )
        )
        coupon_obj = cr.scalar_one_or_none()

    ...

    # 9b. 优惠券使用计数（pending 状态先记录，防止重复使用）
    if coupon_obj:
        coupon_obj.used_count += 1

---

## 审查结论（无需修改）

检查项                      | 文件                     | 结论
---------------------------|--------------------------|-------------------------------
顾客 token 隔离             | deps.py:get_current_customer | role != customer -> 403
管理员 token 隔离           | deps.py:get_current_user    | 独立体系，不混用
地址 CRUD 隔离             | addresses.py               | 全部 customer_id 过滤
订单 preview 安全           | orders.py:preview_order     | 调用 calculate_pricing
订单 create 安全            | orders.py:create_order      | 后端算价 + 库存校验 + 扣减
qty >= 1 校验               | CartItemIn + PricingCartItem | Pydantic ge=1 + Service 层
SKU 校验                    | inventory/pricing.py        | product_id 作用域绑定
跨商品 SKU 混用攻击         | pricing.py                  | variant_pairs 不混淆
积分幂等性                  | orders.py:pay_order          | with_for_update + 幂等返回
优惠券总量校验              | coupons.py                  | usage_limit + used_count
优惠券有效期校验            | coupons.py                  | start_at / end_at
优惠券门槛校验              | coupons.py                  | min_order_amount

---

## 未修复项（已知，暂不处理）

1. 优惠券每人限用（per_customer_limit）
   Discount.extra_rules 字段存在但未被使用。当前没有 customer_id x discount_id
   使用记录表，无法实现限用一人一次。
   影响：同一顾客可反复使用同一张限一次优惠券。
   建议：新增 discount_usage 表。

2. extra_rules 字段未解析
   优惠券可能有限分类限制、用户标签限制，但 validate_coupon 完全未读取。
   建议：在 pricing.py 中增加 extra_rules 解析。

3. 积分恢复时机（minor）
   _do_cancel_order 中 customer.points_balance 在内存直接修改，非 with_for_update。
   影响：低概率竞态。
   建议：改用 await db.execute(select(Customer).where(...).with_for_update())。

---

## 测试结果

cd /data/sme-omnistore-p0-remediated-20260509/backend
PYTHONPATH=/data/sme-omnistore-p0-remediated-20260509/backend   /home/ji/.local/bin/pytest tests/test_order_pricing_inventory_safety.py -v

结果：4 passed ✅

---

## 编译检查

cd /data/sme-omnistore-p0-remediated-20260509/backend
python3 -m compileall -q app migrations tests

结果：无错误输出 ✅
