"""管理员可管理原始读取任务;权限、幂等和异常脱敏由真实接口验证。""" import pytest from sqlalchemy import select from app.core.db import get_session_factory from app.models import TPlusSyncBatch, TPlusSyncError pytestmark = pytest.mark.integration BASE = "/api/v1/system/tplus" def test_未登录和普通用户不能访问管理(client, admin, normal, tplus_tasks): assert client.get(BASE + "/overview").status_code == 401 assert client.get(BASE + "/overview", headers=normal["headers"]).status_code == 403 assert ( client.post(BASE + "/batches", json=tplus_tasks(), headers=normal["headers"]).status_code == 403 ) def test_创建重复请求返回同一批次并可分页查看(client, admin, tplus_tasks): payload = tplus_tasks() first = client.post(BASE + "/batches", json=payload, headers=admin["headers"]) assert first.status_code == 200 second = client.post(BASE + "/batches", json=payload, headers=admin["headers"]) assert second.status_code == 200 number = first.json()["data"]["batch_no"] assert second.json()["data"]["batch_no"] == number page = client.get( BASE + "/batches", params={"pageSize": 1, "status": "QUEUED"}, headers=admin["headers"] ) assert page.status_code == 200 and page.json()["data"]["pageSize"] == 1 detail = client.get(BASE + "/batches/" + number, headers=admin["headers"]) assert detail.status_code == 200 assert detail.json()["data"]["status"] == "QUEUED" def test_异常返回固定说明不泄漏数据库参数(client, admin, tplus_tasks): response = client.post(BASE + "/batches", json=tplus_tasks(), headers=admin["headers"]) assert response.status_code == 200 number = response.json()["data"]["batch_no"] with get_session_factory()() as db: batch = db.scalar(select(TPlusSyncBatch).where(TPlusSyncBatch.batch_no == number)) batch.status, batch.error_message = "FAILED", "password=private-value phone=13800000000" db.add( TPlusSyncError( batch_no=number, entity_type="personnel", source_table="AA_Person", source_id="12", error_code="READ_ERROR", error_message=batch.error_message, ) ) db.commit() for path in (f"/batches/{number}", f"/batches/{number}/errors"): result = client.get(BASE + path, headers=admin["headers"]) assert result.status_code == 200 assert "private-value" not in result.text and "13800000000" not in result.text def test_不支持的实体和不存在的批次有明确错误(client, admin, tplus_tasks): payload = tplus_tasks() payload["entity_types"] = ["users;drop"] assert client.post(BASE + "/batches", json=payload, headers=admin["headers"]).status_code == 400 assert client.get(BASE + "/batches/TPmissing", headers=admin["headers"]).status_code == 404 def test_配置关闭时可查询历史但不能排队(client, admin, tplus_tasks, monkeypatch): from app.services.tplus import task_service settings = task_service.get_settings().model_copy(update={"t_plus_enabled": False}) monkeypatch.setattr(task_service, "get_settings", lambda: settings) response = client.get(BASE + "/overview", headers=admin["headers"]) assert response.status_code == 200 assert response.json()["data"]["is_configured"] is False assert response.json()["data"]["business_import_enabled"] is False assert response.json()["data"]["compatibility_status"] == "PENDING" assert ( client.post(BASE + "/batches", json=tplus_tasks(), headers=admin["headers"]).status_code == 400 ) def test_失败批次重试保留异常并返回新批次(client, admin, tplus_tasks): from app.models import OperationLog parent = client.post(BASE + "/batches", json=tplus_tasks(), headers=admin["headers"]).json()[ "data" ] number = parent["batch_no"] with get_session_factory()() as db: batch = db.scalar(select(TPlusSyncBatch).where(TPlusSyncBatch.batch_no == number)) batch.status, batch.failed_record_count = "FAILED", 1 db.add( TPlusSyncError( batch_no=number, entity_type="personnel", source_table="AA_Person", source_id="1", error_code="READ_ERROR", error_message="读取失败", ) ) db.commit() request = {"request_key": tplus_tasks()["request_key"]} first = client.post(BASE + f"/batches/{number}/retry", json=request, headers=admin["headers"]) replay = client.post(BASE + f"/batches/{number}/retry", json=request, headers=admin["headers"]) assert first.status_code == replay.status_code == 200 child = first.json()["data"] assert child["parent_batch_no"] == number and child["batch_no"] != number assert replay.json()["data"]["batch_no"] == child["batch_no"] detail = client.get(BASE + f"/batches/{number}", headers=admin["headers"]).json()["data"] assert detail["can_retry"] is False with get_session_factory()() as db: assert ( db.scalar(select(TPlusSyncError.retry_count).where(TPlusSyncError.batch_no == number)) == 1 ) assert db.scalar( select(OperationLog.id) .where( OperationLog.user_id == admin["id"], OperationLog.module == "T+数据同步", OperationLog.action == "重试读取任务", ) .limit(1) )