fix: BOM修订功能Bug修复 - bom_number唯一键冲突
问题:
- revise接口生成新版本时bom_number未更新,导致唯一键冲突
修复内容:
1. 修改revise接口逻辑,生成新版本时同步更新bom_number
2. 格式:{原编号}-V{版本号}(如 BOM-001 -> BOM-001-V2)
3. 处理已修订BOM的再次修订(如 BOM-001-V2 -> BOM-001-V3)
4. 添加新编号唯一性检查
新增测试:
- test_revise_bom_creates_unique_bom_number:核心Bug验证
- test_revise_bom_multiple_times:多次修订验证
- test_revise_bom_preserves_items:明细保留验证
- test_revise_already_revised_bom:已修订BOM再修订验证
验收标准:
- ✓ BOM修订功能正常
- ✓ 新版本bom_number唯一
- ✓ 单元测试通过(12 passed)
This commit is contained in:
@@ -386,21 +386,44 @@ async def revise_bom(
|
||||
db: AsyncSession = Depends(get_db),
|
||||
current_user: dict = Depends(get_current_user)
|
||||
):
|
||||
"""创建BOM的新版本"""
|
||||
"""
|
||||
创建BOM的新版本
|
||||
|
||||
- 版本号格式:major.revision (如 1.2)
|
||||
- BOM编号格式:{原编号}-V{版本号} (如 BOM-001-V2)
|
||||
- 新版本状态为DRAFT
|
||||
"""
|
||||
stmt = select(BOMHeader).options(selectinload(BOMHeader.items)).where(BOMHeader.id == bom_id)
|
||||
result = await db.execute(stmt)
|
||||
original = result.scalar_one_or_none()
|
||||
if not original:
|
||||
raise HTTPException(status_code=404, detail=f"BOM ID {bom_id} 不存在")
|
||||
|
||||
# 创建新版本
|
||||
# 计算新版本号
|
||||
new_revision = original.revision + 1
|
||||
version_parts = original.version.split('.')
|
||||
major = int(float(version_parts[0])) if version_parts else 1
|
||||
new_version = f"{major}.{new_revision}"
|
||||
|
||||
# 生成新的BOM编号,格式:{原编号}-V{版本号}
|
||||
# 如果原编号已包含版本后缀(如 -V2),则移除后追加新版本
|
||||
base_number = original.bom_number
|
||||
if "-V" in base_number:
|
||||
# 移除现有版本后缀
|
||||
base_number = base_number.rsplit("-V", 1)[0]
|
||||
new_bom_number = f"{base_number}-V{new_revision}"
|
||||
|
||||
# 确保新编号唯一
|
||||
check_stmt = select(BOMHeader).where(BOMHeader.bom_number == new_bom_number)
|
||||
check_result = await db.execute(check_stmt)
|
||||
if check_result.scalar_one_or_none():
|
||||
raise HTTPException(
|
||||
status_code=400,
|
||||
detail=f"BOM编号 '{new_bom_number}' 已存在,无法创建新版本"
|
||||
)
|
||||
|
||||
new_bom = BOMHeader(
|
||||
bom_number=original.bom_number,
|
||||
bom_number=new_bom_number,
|
||||
bom_name=original.bom_name,
|
||||
description=original.description,
|
||||
version=new_version,
|
||||
|
||||
@@ -1,30 +1,15 @@
|
||||
"""
|
||||
BOM API Unit Tests - PLM System
|
||||
BOM服务测试用例(TD-001 Phase 1)
|
||||
测试修订功能Bug修复
|
||||
"""
|
||||
|
||||
import pytest
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
from app.main import app
|
||||
|
||||
client = TestClient(app)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def auth_token():
|
||||
"""获取认证Token"""
|
||||
response = client.post(
|
||||
"/api/v1/auth/login",
|
||||
json={"username": "admin", "password": "Admin@123456"}
|
||||
)
|
||||
if response.status_code == 200:
|
||||
return response.json()["access_token"]
|
||||
return None
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def test_bom_id(auth_token):
|
||||
@pytest.fixture(scope="session")
|
||||
def test_bom_id(client: TestClient, auth_token: str):
|
||||
"""创建测试BOM并返回ID"""
|
||||
if not auth_token:
|
||||
return None
|
||||
@@ -57,7 +42,7 @@ def test_bom_id(auth_token):
|
||||
class TestBOMHeaderAPI:
|
||||
"""BOM头API测试类"""
|
||||
|
||||
def test_create_bom(self, auth_token):
|
||||
def test_create_bom(self, client: TestClient, auth_token: str):
|
||||
"""测试创建BOM"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -75,7 +60,7 @@ class TestBOMHeaderAPI:
|
||||
)
|
||||
assert response.status_code in [201, 400] # 400可能是已存在
|
||||
|
||||
def test_create_bom_duplicate_number(self, auth_token):
|
||||
def test_create_bom_duplicate_number(self, client: TestClient, auth_token: str):
|
||||
"""测试创建重复编号BOM"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -103,7 +88,7 @@ class TestBOMHeaderAPI:
|
||||
)
|
||||
assert response.status_code == 400
|
||||
|
||||
def test_list_boms(self, auth_token):
|
||||
def test_list_boms(self, client: TestClient, auth_token: str):
|
||||
"""测试获取BOM列表"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -117,7 +102,7 @@ class TestBOMHeaderAPI:
|
||||
assert "total" in data
|
||||
assert "data" in data
|
||||
|
||||
def test_list_boms_with_filter(self, auth_token):
|
||||
def test_list_boms_with_filter(self, client: TestClient, auth_token: str):
|
||||
"""测试带筛选条件的BOM列表"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -129,7 +114,7 @@ class TestBOMHeaderAPI:
|
||||
data = response.json()
|
||||
assert data["success"] is True
|
||||
|
||||
def test_get_bom_detail(self, auth_token, test_bom_id):
|
||||
def test_get_bom_detail(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试获取BOM详情"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -141,7 +126,7 @@ class TestBOMHeaderAPI:
|
||||
data = response.json()
|
||||
assert "bom_number" in data
|
||||
|
||||
def test_get_bom_not_found(self, auth_token):
|
||||
def test_get_bom_not_found(self, client: TestClient, auth_token: str):
|
||||
"""测试获取不存在的BOM"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -151,7 +136,7 @@ class TestBOMHeaderAPI:
|
||||
)
|
||||
assert response.status_code == 404
|
||||
|
||||
def test_update_bom(self, auth_token, test_bom_id):
|
||||
def test_update_bom(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试更新BOM"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -162,7 +147,7 @@ class TestBOMHeaderAPI:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_delete_bom(self, auth_token):
|
||||
def test_delete_bom(self, client: TestClient, auth_token: str):
|
||||
"""测试删除BOM"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -189,7 +174,7 @@ class TestBOMHeaderAPI:
|
||||
class TestBOMItemAPI:
|
||||
"""BOM明细API测试类"""
|
||||
|
||||
def test_add_bom_item(self, auth_token, test_bom_id):
|
||||
def test_add_bom_item(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试添加BOM明细"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -206,7 +191,7 @@ class TestBOMItemAPI:
|
||||
)
|
||||
assert response.status_code == 201
|
||||
|
||||
def test_list_bom_items(self, auth_token, test_bom_id):
|
||||
def test_list_bom_items(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试获取BOM明细列表"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -216,7 +201,7 @@ class TestBOMItemAPI:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_update_bom_item(self, auth_token, test_bom_id):
|
||||
def test_update_bom_item(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试更新BOM明细"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -234,7 +219,7 @@ class TestBOMItemAPI:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_bom_item_quantity_boundary(self, auth_token, test_bom_id):
|
||||
def test_bom_item_quantity_boundary(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试BOM明细数量边界值"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -257,7 +242,7 @@ class TestBOMItemAPI:
|
||||
class TestBOMStatusAPI:
|
||||
"""BOM状态管理测试"""
|
||||
|
||||
def test_activate_bom(self, auth_token, test_bom_id):
|
||||
def test_activate_bom(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试激活BOM"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -267,7 +252,7 @@ class TestBOMStatusAPI:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_obsolete_bom(self, auth_token):
|
||||
def test_obsolete_bom(self, client: TestClient, auth_token: str):
|
||||
"""测试作废BOM"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -294,7 +279,7 @@ class TestBOMStatusAPI:
|
||||
class TestBOMAIAPI:
|
||||
"""BOM AI分析测试"""
|
||||
|
||||
def test_ai_analyze_bom(self, auth_token, test_bom_id):
|
||||
def test_ai_analyze_bom(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试AI分析BOM"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -307,7 +292,7 @@ class TestBOMAIAPI:
|
||||
assert "recommendation" in data
|
||||
assert "cost_estimate" in data
|
||||
|
||||
def test_ai_analyze_cost(self, auth_token, test_bom_id):
|
||||
def test_ai_analyze_cost(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试AI成本分析"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -317,7 +302,7 @@ class TestBOMAIAPI:
|
||||
)
|
||||
assert response.status_code in [200, 404]
|
||||
|
||||
def test_ai_analyze_risk(self, auth_token, test_bom_id):
|
||||
def test_ai_analyze_risk(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试AI风险分析"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -331,7 +316,7 @@ class TestBOMAIAPI:
|
||||
class TestBOMTreeView:
|
||||
"""BOM树形展示测试"""
|
||||
|
||||
def test_get_bom_tree_view(self, auth_token, test_bom_id):
|
||||
def test_get_bom_tree_view(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试获取BOM树形结构"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -343,7 +328,7 @@ class TestBOMTreeView:
|
||||
data = response.json()
|
||||
assert "items" in data
|
||||
|
||||
def test_get_bom_flat_view(self, auth_token, test_bom_id):
|
||||
def test_get_bom_flat_view(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试获取BOM平铺结构"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -353,7 +338,7 @@ class TestBOMTreeView:
|
||||
)
|
||||
assert response.status_code == 200
|
||||
|
||||
def test_bom_tree_with_children(self, auth_token):
|
||||
def test_bom_tree_with_children(self, client: TestClient, auth_token: str):
|
||||
"""测试BOM树形结构 - 带子件"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
@@ -390,9 +375,9 @@ class TestBOMTreeView:
|
||||
|
||||
|
||||
class TestBOMVersionAPI:
|
||||
"""BOM版本管理测试"""
|
||||
"""BOM版本管理测试 - 验证修订Bug修复"""
|
||||
|
||||
def test_revise_bom(self, auth_token, test_bom_id):
|
||||
def test_revise_bom(self, client: TestClient, auth_token: str, test_bom_id: int):
|
||||
"""测试修订BOM(创建新版本)"""
|
||||
if not auth_token or not test_bom_id:
|
||||
pytest.skip("需要认证Token和测试BOM")
|
||||
@@ -405,6 +390,283 @@ class TestBOMVersionAPI:
|
||||
# 版本号应该增加
|
||||
assert "version" in data
|
||||
|
||||
def test_revise_bom_creates_unique_bom_number(self, client: TestClient, auth_token: str):
|
||||
"""
|
||||
测试修订BOM时生成唯一的bom_number
|
||||
|
||||
验证修复:revise接口生成新版本时bom_number应更新
|
||||
- 原编号:BOM-REVISE-001
|
||||
- 新编号:BOM-REVISE-001-V2
|
||||
|
||||
这是核心Bug修复验证测试!
|
||||
"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
|
||||
# 创建原始BOM
|
||||
create_response = client.post(
|
||||
"/api/v1/bom",
|
||||
headers={"Authorization": f"Bearer {auth_token}"},
|
||||
json={
|
||||
"bom_number": "BOM-REVISE-001",
|
||||
"bom_name": "修订测试BOM",
|
||||
"description": "测试修订功能",
|
||||
"version": "1.0",
|
||||
"revision": 1,
|
||||
"product_id": 1,
|
||||
"items": [
|
||||
{
|
||||
"item_number": "ITEM-REVISE-001",
|
||||
"item_name": "测试物料",
|
||||
"item_type": "material",
|
||||
"quantity": 10,
|
||||
"unit": "pcs"
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
original_bom_number = "BOM-REVISE-001"
|
||||
|
||||
if create_response.status_code == 201:
|
||||
bom_id = create_response.json()["id"]
|
||||
elif create_response.status_code == 400:
|
||||
# BOM已存在,获取其ID
|
||||
list_response = client.get(
|
||||
"/api/v1/bom?keyword=BOM-REVISE-001",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
if list_response.status_code == 200 and list_response.json()["data"]:
|
||||
bom_id = list_response.json()["data"][0]["id"]
|
||||
else:
|
||||
pytest.skip("无法获取测试BOM")
|
||||
else:
|
||||
pytest.skip(f"创建测试BOM失败: {create_response.status_code}")
|
||||
|
||||
# 执行修订
|
||||
revise_response = client.post(
|
||||
f"/api/v1/bom/{bom_id}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
|
||||
assert revise_response.status_code == 200, f"修订失败: {revise_response.text}"
|
||||
revised_data = revise_response.json()
|
||||
|
||||
# 验证:新版本的bom_number应该是唯一的,格式为 {原编号}-V{版本号}
|
||||
assert "bom_number" in revised_data
|
||||
new_bom_number = revised_data["bom_number"]
|
||||
|
||||
# 核心验证:bom_number必须更新
|
||||
assert new_bom_number != original_bom_number, \
|
||||
f"❌ Bug未修复!bom_number未更新,原编号和新编号相同: {original_bom_number}"
|
||||
|
||||
# 验证格式正确
|
||||
assert "-V" in new_bom_number, \
|
||||
f"bom_number格式不正确,应包含版本后缀: {new_bom_number}"
|
||||
assert new_bom_number == "BOM-REVISE-001-V2", \
|
||||
f"bom_number格式不正确,期望 BOM-REVISE-001-V2,实际: {new_bom_number}"
|
||||
|
||||
# 验证版本号正确
|
||||
assert revised_data["revision"] == 2, "版本号应为2"
|
||||
assert revised_data["version"] == "1.2", "版本号格式应为 1.2"
|
||||
|
||||
# 验证状态为DRAFT
|
||||
assert revised_data["status"] == "draft", "新版本状态应为draft"
|
||||
|
||||
# 验证新编号唯一(不会与原编号冲突)
|
||||
check_response = client.get(
|
||||
f"/api/v1/bom?keyword={new_bom_number}",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert check_response.status_code == 200
|
||||
|
||||
def test_revise_bom_multiple_times(self, client: TestClient, auth_token: str):
|
||||
"""
|
||||
测试多次修订BOM,确保每次都生成唯一的bom_number
|
||||
|
||||
- 第一次修订:BOM-MULTI-001 -> BOM-MULTI-001-V2
|
||||
- 第二次修订:BOM-MULTI-001-V2 -> BOM-MULTI-001-V3
|
||||
"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
|
||||
# 创建原始BOM
|
||||
create_response = client.post(
|
||||
"/api/v1/bom",
|
||||
headers={"Authorization": f"Bearer {auth_token}"},
|
||||
json={
|
||||
"bom_number": "BOM-MULTI-001",
|
||||
"bom_name": "多次修订测试BOM",
|
||||
"version": "1.0",
|
||||
"revision": 1,
|
||||
"product_id": 1
|
||||
}
|
||||
)
|
||||
|
||||
if create_response.status_code == 201:
|
||||
original_bom_id = create_response.json()["id"]
|
||||
elif create_response.status_code == 400:
|
||||
# BOM已存在,获取其ID
|
||||
list_response = client.get(
|
||||
"/api/v1/bom?keyword=BOM-MULTI-001",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
if list_response.status_code == 200 and list_response.json()["data"]:
|
||||
original_bom_id = list_response.json()["data"][0]["id"]
|
||||
else:
|
||||
pytest.skip("无法获取测试BOM")
|
||||
else:
|
||||
pytest.skip("创建测试BOM失败")
|
||||
|
||||
# 第一次修订
|
||||
revise1_response = client.post(
|
||||
f"/api/v1/bom/{original_bom_id}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert revise1_response.status_code == 200, f"第一次修订失败: {revise1_response.text}"
|
||||
revised1 = revise1_response.json()
|
||||
assert revised1["bom_number"] == "BOM-MULTI-001-V2", \
|
||||
f"第一次修订bom_number错误: {revised1['bom_number']}"
|
||||
|
||||
# 第二次修订(基于第一次修订的版本)
|
||||
revise2_response = client.post(
|
||||
f"/api/v1/bom/{revised1['id']}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert revise2_response.status_code == 200, f"第二次修订失败: {revise2_response.text}"
|
||||
revised2 = revise2_response.json()
|
||||
assert revised2["bom_number"] == "BOM-MULTI-001-V3", \
|
||||
f"第二次修订bom_number错误: {revised2['bom_number']}"
|
||||
|
||||
# 验证所有版本的bom_number都是唯一的
|
||||
bom_numbers = [revised1["bom_number"], revised2["bom_number"]]
|
||||
assert len(bom_numbers) == len(set(bom_numbers)), "bom_number应该唯一"
|
||||
|
||||
def test_revise_bom_preserves_items(self, client: TestClient, auth_token: str):
|
||||
"""测试修订BOM时保留原有明细项"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
|
||||
# 创建带明细的BOM
|
||||
create_response = client.post(
|
||||
"/api/v1/bom",
|
||||
headers={"Authorization": f"Bearer {auth_token}"},
|
||||
json={
|
||||
"bom_number": "BOM-ITEMS-001",
|
||||
"bom_name": "明细保留测试BOM",
|
||||
"version": "1.0",
|
||||
"revision": 1,
|
||||
"product_id": 1,
|
||||
"items": [
|
||||
{
|
||||
"item_number": "ITEM-PRESERVE-001",
|
||||
"item_name": "测试物料1",
|
||||
"item_type": "material",
|
||||
"quantity": 10,
|
||||
"unit": "pcs"
|
||||
},
|
||||
{
|
||||
"item_number": "ITEM-PRESERVE-002",
|
||||
"item_name": "测试物料2",
|
||||
"item_type": "material",
|
||||
"quantity": 20,
|
||||
"unit": "kg"
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
original_items_count = 2
|
||||
|
||||
if create_response.status_code == 201:
|
||||
bom_id = create_response.json()["id"]
|
||||
elif create_response.status_code == 400:
|
||||
list_response = client.get(
|
||||
"/api/v1/bom?keyword=BOM-ITEMS-001",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
if list_response.status_code == 200 and list_response.json()["data"]:
|
||||
bom_id = list_response.json()["data"][0]["id"]
|
||||
else:
|
||||
pytest.skip("无法获取测试BOM")
|
||||
else:
|
||||
pytest.skip("创建测试BOM失败")
|
||||
|
||||
# 执行修订
|
||||
revise_response = client.post(
|
||||
f"/api/v1/bom/{bom_id}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert revise_response.status_code == 200
|
||||
|
||||
# 获取新版本的明细
|
||||
revised_bom_id = revise_response.json()["id"]
|
||||
items_response = client.get(
|
||||
f"/api/v1/bom/{revised_bom_id}/items",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert items_response.status_code == 200
|
||||
items = items_response.json()
|
||||
assert len(items) == original_items_count, "修订后明细数量应保持一致"
|
||||
|
||||
def test_revise_already_revised_bom(self, client: TestClient, auth_token: str):
|
||||
"""
|
||||
测试修订已修订过的BOM
|
||||
|
||||
验证:已带版本后缀的BOM(如 BOM-001-V2)再次修订时
|
||||
应生成 BOM-001-V3,而非 BOM-001-V2-V3
|
||||
"""
|
||||
if not auth_token:
|
||||
pytest.skip("需要认证Token")
|
||||
|
||||
# 创建原始BOM并修订一次
|
||||
create_response = client.post(
|
||||
"/api/v1/bom",
|
||||
headers={"Authorization": f"Bearer {auth_token}"},
|
||||
json={
|
||||
"bom_number": "BOM-RE-REVISE-001",
|
||||
"bom_name": "再修订测试BOM",
|
||||
"version": "1.0",
|
||||
"revision": 1,
|
||||
"product_id": 1
|
||||
}
|
||||
)
|
||||
|
||||
if create_response.status_code == 201:
|
||||
bom_id = create_response.json()["id"]
|
||||
elif create_response.status_code == 400:
|
||||
list_response = client.get(
|
||||
"/api/v1/bom?keyword=BOM-RE-REVISE-001",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
if list_response.status_code == 200 and list_response.json()["data"]:
|
||||
bom_id = list_response.json()["data"][0]["id"]
|
||||
else:
|
||||
pytest.skip("无法获取测试BOM")
|
||||
else:
|
||||
pytest.skip("创建测试BOM失败")
|
||||
|
||||
# 第一次修订
|
||||
revise1 = client.post(
|
||||
f"/api/v1/bom/{bom_id}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert revise1.status_code == 200
|
||||
v2_data = revise1.json()
|
||||
assert v2_data["bom_number"] == "BOM-RE-REVISE-001-V2"
|
||||
|
||||
# 第二次修订(基于V2版本)
|
||||
revise2 = client.post(
|
||||
f"/api/v1/bom/{v2_data['id']}/revise",
|
||||
headers={"Authorization": f"Bearer {auth_token}"}
|
||||
)
|
||||
assert revise2.status_code == 200
|
||||
v3_data = revise2.json()
|
||||
|
||||
# 验证:应该是 BOM-RE-REVISE-001-V3,而不是 BOM-RE-REVISE-001-V2-V3
|
||||
assert v3_data["bom_number"] == "BOM-RE-REVISE-001-V3", \
|
||||
f"修订已修订BOM时编号处理错误: 期望 BOM-RE-REVISE-001-V3,实际 {v3_data['bom_number']}"
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user