153 lines
4.6 KiB
Python
153 lines
4.6 KiB
Python
"""服务项目接口测试"""
|
|
|
|
import pytest
|
|
from httpx import AsyncClient
|
|
|
|
from app.models import Project, Category, Material, Equipment, StaffLevel
|
|
from tests.conftest import assert_response_success
|
|
|
|
|
|
class TestProjectsAPI:
|
|
"""服务项目 API 测试"""
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_create_project(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_category: Category
|
|
):
|
|
"""测试创建项目"""
|
|
response = await client.post(
|
|
"/api/v1/projects",
|
|
json={
|
|
"project_code": "PRJ_TEST001",
|
|
"project_name": "测试项目",
|
|
"category_id": sample_category.id,
|
|
"description": "测试项目描述",
|
|
"duration_minutes": 45,
|
|
"is_active": True
|
|
}
|
|
)
|
|
|
|
data = assert_response_success(response)
|
|
assert data["project_code"] == "PRJ_TEST001"
|
|
assert data["project_name"] == "测试项目"
|
|
assert data["duration_minutes"] == 45
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_get_projects_list(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project: Project
|
|
):
|
|
"""测试获取项目列表"""
|
|
response = await client.get("/api/v1/projects")
|
|
|
|
data = assert_response_success(response)
|
|
assert "items" in data
|
|
assert data["total"] >= 1
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_get_project_detail(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project: Project
|
|
):
|
|
"""测试获取项目详情"""
|
|
response = await client.get(f"/api/v1/projects/{sample_project.id}")
|
|
|
|
data = assert_response_success(response)
|
|
assert data["id"] == sample_project.id
|
|
assert data["project_name"] == sample_project.project_name
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_add_cost_item(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project: Project,
|
|
sample_material: Material
|
|
):
|
|
"""测试添加成本明细"""
|
|
response = await client.post(
|
|
f"/api/v1/projects/{sample_project.id}/cost-items",
|
|
json={
|
|
"item_type": "material",
|
|
"item_id": sample_material.id,
|
|
"quantity": 5,
|
|
"remark": "测试备注"
|
|
}
|
|
)
|
|
|
|
data = assert_response_success(response)
|
|
assert data["item_type"] == "material"
|
|
assert float(data["quantity"]) == 5.0
|
|
assert float(data["total_cost"]) == 10.0 # 5 * 2.00
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_add_labor_cost(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project: Project,
|
|
sample_staff_level: StaffLevel
|
|
):
|
|
"""测试添加人工成本"""
|
|
response = await client.post(
|
|
f"/api/v1/projects/{sample_project.id}/labor-costs",
|
|
json={
|
|
"staff_level_id": sample_staff_level.id,
|
|
"duration_minutes": 30
|
|
}
|
|
)
|
|
|
|
data = assert_response_success(response)
|
|
assert data["duration_minutes"] == 30
|
|
assert float(data["labor_cost"]) == 25.0 # 30/60 * 50
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_calculate_project_cost(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project_with_costs: Project
|
|
):
|
|
"""测试计算项目成本"""
|
|
response = await client.post(
|
|
f"/api/v1/projects/{sample_project_with_costs.id}/calculate-cost",
|
|
json={"allocation_method": "count"}
|
|
)
|
|
|
|
data = assert_response_success(response)
|
|
assert data["project_id"] == sample_project_with_costs.id
|
|
assert "cost_breakdown" in data
|
|
assert "total_cost" in data
|
|
assert data["total_cost"] > 0
|
|
|
|
@pytest.mark.api
|
|
@pytest.mark.asyncio
|
|
async def test_get_cost_summary(
|
|
self,
|
|
client: AsyncClient,
|
|
sample_project_with_costs: Project
|
|
):
|
|
"""测试获取成本汇总"""
|
|
# 先计算成本
|
|
await client.post(
|
|
f"/api/v1/projects/{sample_project_with_costs.id}/calculate-cost",
|
|
json={"allocation_method": "count"}
|
|
)
|
|
|
|
# 获取汇总
|
|
response = await client.get(
|
|
f"/api/v1/projects/{sample_project_with_costs.id}/cost-summary"
|
|
)
|
|
|
|
data = assert_response_success(response)
|
|
assert data["project_id"] == sample_project_with_costs.id
|
|
assert "material_cost" in data
|
|
assert "total_cost" in data
|