"""PROD-001 ~ PROD-008: 产品与产品分类管理测试。 覆盖功能点: - 产品分类 CRUD - 产品 CRUD - 产品状态校验 """ from __future__ import annotations import pytest @pytest.mark.product @pytest.mark.p1 class TestProductCategory: """PROD-001 ~ PROD-003: 产品分类测试。""" def test_create_category_success(self, client, admin_headers): """PROD-001: 新增产品分类成功。""" resp = client.post("/api/product-categories", headers=admin_headers, json={ "category_name": "测试分类", "category_code": "TEST_CAT_001", "sort_no": 1, }) assert resp.status_code == 200 data = resp.json() assert data["code"] == 0 def test_duplicate_category_code(self, client, admin_headers, db_session): """PROD-002: 分类编码重复应返回 40006。""" from backend.app.models.business import ProductCategory cat = ProductCategory(category_name="已有分类", category_code="EXISTING_CODE", status=1) db_session.add(cat) db_session.flush() resp = client.post("/api/product-categories", headers=admin_headers, json={ "category_name": "新分类", "category_code": "EXISTING_CODE", }) assert resp.status_code in (400, 409) def test_disable_category(self, client, admin_headers, db_session): """PROD-003: 停用分类。""" from backend.app.models.business import ProductCategory cat = ProductCategory(category_name="待停用", category_code="TO_DISABLE", status=1) db_session.add(cat) db_session.flush() resp = client.put(f"/api/product-categories/{cat.id}", headers=admin_headers, json={ "category_name": "待停用", "category_code": "TO_DISABLE", "status": 0, }) assert resp.status_code == 200 @pytest.mark.product @pytest.mark.p1 class TestProduct: """PROD-004 ~ PROD-008: 产品测试。""" def test_create_product_success(self, client, admin_headers, db_session): """PROD-004: 新增产品成功。 注意: CreateProductRequest 需要 specifications 列表(至少一个规格) """ from backend.app.models.business import ProductCategory cat = ProductCategory(category_name="产品测试分类", category_code="PROD_TEST_CAT", status=1) db_session.add(cat) db_session.flush() resp = client.post("/api/products", headers=admin_headers, json={ "product_name": "测试产品X", "category_id": cat.id, "specifications": [{ "specification": "100x100cm", "unit": "张", "cost_price": 50, "sale_price": 100, }], }) assert resp.status_code == 200 data = resp.json() assert data["code"] == 0 def test_product_list_filter(self, client, admin_headers, make_product): """PROD-005: 产品列表筛选。""" make_product(product_name="铝板产品") make_product(product_name="钢材产品") resp = client.get("/api/products?keyword=铝板", headers=admin_headers) assert resp.status_code == 200 def test_product_detail(self, client, admin_headers, make_product): """PROD-006: 产品详情。""" product = make_product() resp = client.get(f"/api/products/{product.id}", headers=admin_headers) assert resp.status_code == 200 data = resp.json()["data"] assert data["product_name"] is not None def test_disabled_product_flag(self, client, admin_headers, make_product): """PROD-007: 禁用产品标识。""" product = make_product(status=0) resp = client.get(f"/api/products/{product.id}", headers=admin_headers) assert resp.status_code == 200 # 产品详情接口可能过滤已删除(deleted=1)的产品,但 status=0 的产品应该能查到 data = resp.json()["data"] # 确认返回的是该产品 assert data["product_name"] == product.product_name @pytest.mark.product @pytest.mark.p0 class TestProductOrderConstraint: """PROD-007: 禁用产品下单约束测试。""" def test_disabled_product_cannot_order(self, client, salesman_headers, make_product): """PROD-007: 禁用产品不能创建订单。""" product = make_product(status=0) resp = client.post("/api/orders", headers=salesman_headers, json={ "customer_name": "禁用产品测试客户", "customer_mobile": "1380000P007", "items": [{ "product_id": product.id, "product_name": product.product_name, "specification": product.specification, "unit": product.unit, "quantity": 1, "sale_price": 100, "cost_price": 60, }], }) # 应被拒绝或有警告 assert resp.status_code in (400, 200)