"""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