PayrollManagementSystem/backend/tests/integration/test_tplus_management.py

130 lines
5.5 KiB
Python

"""管理员可管理原始读取任务;权限、幂等和异常脱敏由真实接口验证。"""
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)
)