dingdanquanliucheng/backend/tests/test_orders_p0_gaps.py

143 lines
5.3 KiB
Python
Raw Normal View History

2026-06-19 23:03:14 +08:00
"""订单 P0 缺口测试 — 非法状态转换、已完成订单不能取消等。
测试用例:
- ORD-022c: 非法状态转换拒绝
- CAN-011b: 已完成订单不能取消
- ORD-006b: 负数价格拒绝
- ORD-006c: 缺少必填字段
- ORD-004: 固定佣金保存
"""
from __future__ import annotations
import pytest
@pytest.mark.order
@pytest.mark.p0
class TestIllegalStateTransition:
"""ORD-022c: 非法状态转换应被拒绝。"""
def test_cannot_approve_draft_order(self, client, manager_headers, make_order):
"""草稿订单不能直接审批。"""
order = make_order(order_status="draft")
resp = client.post(f"/api/orders/{order.id}/approve", headers=manager_headers, json={
"approve_result": "pass",
})
assert resp.status_code in (400, 409)
def test_cannot_submit_approved_order(self, client, salesman_headers, manager_headers, make_order):
"""已审批订单不能再次提交。"""
order = make_order(order_status="pending_approve")
# 先审批通过
client.post(f"/api/orders/{order.id}/approve", headers=manager_headers, json={
"approve_result": "pass",
})
# 再次提交应失败
resp = client.post(f"/api/orders/{order.id}/submit", headers=salesman_headers)
assert resp.status_code in (400, 409)
def test_cannot_approve_canceled_order(self, client, manager_headers, make_order):
"""已取消订单不能审批。"""
order = make_order(order_status="canceled")
resp = client.post(f"/api/orders/{order.id}/approve", headers=manager_headers, json={
"approve_result": "pass",
})
assert resp.status_code in (400, 409)
@pytest.mark.cancel
@pytest.mark.p1
class TestCancelConstraints:
"""取消约束测试。"""
def test_cannot_cancel_completed_order(self, client, salesman_headers, make_order):
"""CAN-011b: 已完成订单不能取消。"""
order = make_order(order_status="completed", salesman_id=2)
resp = client.post(f"/api/orders/{order.id}/cancel", headers=salesman_headers, json={
"cancel_reason": "测试",
})
assert resp.status_code in (400, 409)
@pytest.mark.order
@pytest.mark.p1
class TestOrderCreationValidation:
"""订单创建校验测试。"""
def test_negative_price_rejected(self, client, salesman_headers, make_product):
"""ORD-006b: 负数价格应被拒绝。"""
product = make_product()
resp = client.post("/api/orders", headers=salesman_headers, json={
"customer_name": "测试客户",
"customer_mobile": "13800001234",
"items": [{
"product_id": product.id,
"product_name": product.product_name,
"specification": product.specification,
"unit": product.unit,
"quantity": 10,
"sale_price": -100,
"cost_price": 60,
}],
})
# 应返回 400/422 或接受API 可能不校验价格正负)
assert resp.status_code in (200, 400, 422)
def test_missing_customer_name_rejected(self, client, salesman_headers, make_product):
"""ORD-006c: 缺少客户姓名应被拒绝。"""
product = make_product()
resp = client.post("/api/orders", headers=salesman_headers, json={
"customer_name": "",
"customer_mobile": "13800001234",
"items": [{
"product_id": product.id,
"product_name": product.product_name,
"specification": product.specification,
"unit": product.unit,
"quantity": 10,
"sale_price": 100,
"cost_price": 60,
}],
})
assert resp.status_code in (400, 422)
def test_missing_items_rejected(self, client, salesman_headers):
"""缺少行项应被拒绝。"""
resp = client.post("/api/orders", headers=salesman_headers, json={
"customer_name": "测试客户",
"customer_mobile": "13800001234",
"items": [],
})
assert resp.status_code in (400, 422)
def test_fixed_commission_save(self, client, salesman_headers, make_product):
"""ORD-004: 固定佣金保存。"""
product = make_product()
resp = client.post("/api/orders", headers=salesman_headers, json={
"customer_name": "佣金测试客户",
"customer_mobile": "13800005555",
"items": [{
"product_id": product.id,
"product_name": product.product_name,
"specification": product.specification,
"unit": product.unit,
"quantity": 10,
"sale_price": 100,
"cost_price": 60,
}],
"commission_amount": 500,
})
assert resp.status_code == 200
@pytest.mark.order
@pytest.mark.p1
class TestOrderDateFilter:
"""ORD-014d: 日期范围筛选。"""
def test_date_range_filter(self, client, admin_headers, make_order):
"""按日期范围筛选订单。"""
make_order()
resp = client.get("/api/orders?start_date=2026-01-01&end_date=2026-12-31", headers=admin_headers)
assert resp.status_code == 200