168 lines
5.9 KiB
Python
168 lines
5.9 KiB
Python
"""AUD-001 ~ AUD-008: 审计日志测试。
|
|
|
|
覆盖功能点:
|
|
- 订单创建审计
|
|
- 审批审计
|
|
- 取消审计
|
|
- 审计日志查询和筛选
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import pytest
|
|
|
|
|
|
@pytest.mark.audit
|
|
@pytest.mark.p0
|
|
class TestAuditLogWriting:
|
|
"""AUD-001 ~ AUD-004: 审计日志写入测试。"""
|
|
|
|
def test_order_create_audit(self, client, salesman_headers, make_product, db_session):
|
|
"""AUD-001: 订单创建应记录审计日志。"""
|
|
from backend.app.models.system import AuditLog
|
|
product = make_product()
|
|
client.post("/api/orders", headers=salesman_headers, json={
|
|
"customer_name": "审计测试客户",
|
|
"customer_mobile": "1380000A001",
|
|
"items": [{
|
|
"product_id": product.id,
|
|
"product_name": product.product_name,
|
|
"specification": product.specification,
|
|
"unit": product.unit,
|
|
"quantity": 5,
|
|
"sale_price": 100,
|
|
"cost_price": 60,
|
|
}],
|
|
})
|
|
|
|
# 检查审计日志
|
|
audit = db_session.query(AuditLog).filter(
|
|
AuditLog.operate_type == "order_create",
|
|
AuditLog.biz_type == "sales_order",
|
|
).first()
|
|
assert audit is not None, "订单创建应生成审计日志"
|
|
|
|
def test_approval_audit(self, client, salesman_headers, manager_headers, make_product, db_session):
|
|
"""AUD-002: 审批应记录审计日志。"""
|
|
from backend.app.models.system import AuditLog
|
|
product = make_product()
|
|
create_resp = client.post("/api/orders", headers=salesman_headers, json={
|
|
"customer_name": "审批审计客户",
|
|
"customer_mobile": "1380000A002",
|
|
"items": [{
|
|
"product_id": product.id,
|
|
"product_name": product.product_name,
|
|
"specification": product.specification,
|
|
"unit": product.unit,
|
|
"quantity": 5,
|
|
"sale_price": 100,
|
|
"cost_price": 60,
|
|
}],
|
|
})
|
|
order_id = create_resp.json()["data"]["order_id"]
|
|
client.post(f"/api/orders/{order_id}/submit", headers=salesman_headers)
|
|
client.post(f"/api/orders/{order_id}/approve", headers=manager_headers, json={
|
|
"approve_result": "pass",
|
|
})
|
|
|
|
# 检查审计日志
|
|
audit = db_session.query(AuditLog).filter(
|
|
AuditLog.operate_type == "order_approve",
|
|
AuditLog.biz_type == "sales_order",
|
|
).first()
|
|
assert audit is not None, "订单审批应生成审计日志"
|
|
|
|
def test_cancel_audit(self, client, salesman_headers, make_product, db_session):
|
|
"""AUD-003: 取消应记录审计日志。"""
|
|
from backend.app.models.system import AuditLog
|
|
product = make_product()
|
|
create_resp = client.post("/api/orders", headers=salesman_headers, json={
|
|
"customer_name": "取消审计客户",
|
|
"customer_mobile": "1380000A003",
|
|
"items": [{
|
|
"product_id": product.id,
|
|
"product_name": product.product_name,
|
|
"specification": product.specification,
|
|
"unit": product.unit,
|
|
"quantity": 5,
|
|
"sale_price": 100,
|
|
"cost_price": 60,
|
|
}],
|
|
})
|
|
order_id = create_resp.json()["data"]["order_id"]
|
|
client.post(f"/api/orders/{order_id}/cancel", headers=salesman_headers, json={
|
|
"cancel_reason": "审计测试取消",
|
|
})
|
|
|
|
# 检查审计日志
|
|
audit = db_session.query(AuditLog).filter(
|
|
AuditLog.operate_type == "order_cancel",
|
|
AuditLog.biz_type == "sales_order",
|
|
).first()
|
|
assert audit is not None, "订单取消应生成审计日志"
|
|
|
|
|
|
@pytest.mark.audit
|
|
@pytest.mark.p1
|
|
class TestAuditLogQuery:
|
|
"""AUD-008: 审计日志查询测试。"""
|
|
|
|
def test_audit_log_list(self, client, admin_headers, db_session):
|
|
"""AUD-008: 审计日志列表查询。"""
|
|
from backend.app.models.system import AuditLog
|
|
|
|
# 预置审计日志
|
|
audit = AuditLog(
|
|
operator_id=1,
|
|
operator_name="管理员",
|
|
operate_type="create",
|
|
biz_type="order",
|
|
biz_id=1,
|
|
result="success",
|
|
)
|
|
db_session.add(audit)
|
|
db_session.flush()
|
|
|
|
resp = client.get("/api/audit-logs", headers=admin_headers)
|
|
assert resp.status_code == 200
|
|
data = resp.json()
|
|
assert "list" in data["data"]
|
|
|
|
def test_audit_log_filter(self, client, admin_headers, db_session):
|
|
"""审计日志筛选。"""
|
|
from backend.app.models.system import AuditLog
|
|
|
|
audit = AuditLog(
|
|
operator_id=1,
|
|
operator_name="管理员",
|
|
operate_type="approve",
|
|
biz_type="order",
|
|
biz_id=2,
|
|
result="success",
|
|
)
|
|
db_session.add(audit)
|
|
db_session.flush()
|
|
|
|
resp = client.get("/api/audit-logs?operate_type=approve", headers=admin_headers)
|
|
assert resp.status_code == 200
|
|
|
|
|
|
@pytest.mark.audit
|
|
@pytest.mark.p1
|
|
class TestAuditPermission:
|
|
"""审计日志权限测试。"""
|
|
|
|
def test_salesman_cannot_view_audit(self, client, salesman_headers):
|
|
"""业务员不能查看审计日志。"""
|
|
resp = client.get("/api/audit-logs", headers=salesman_headers)
|
|
assert resp.status_code == 403
|
|
|
|
def test_driver_cannot_view_audit(self, client, driver_headers):
|
|
"""司机不能查看审计日志。"""
|
|
resp = client.get("/api/audit-logs", headers=driver_headers)
|
|
assert resp.status_code == 403
|
|
|
|
def test_admin_can_view_audit(self, client, admin_headers):
|
|
"""管理员可以查看审计日志。"""
|
|
resp = client.get("/api/audit-logs", headers=admin_headers)
|
|
assert resp.status_code == 200
|