PayrollManagementSystem/backend/tests/unit/test_tplus_worker_business_sync.py
liuwenxin 1e53792ad6 feat(T+): 完成数据贯通与自动接入闭环
打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。
新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。
补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
2026-11-05 18:47:13 +08:00

80 lines
3.0 KiB
Python

"""采集与业务接入分别记录结果。"""
from contextlib import nullcontext
from datetime import date
from types import SimpleNamespace
import pytest
from sqlalchemy.exc import IntegrityError
from app.core.exceptions import BadRequestError, ConflictError
from app.services.tplus import business_sync_control, worker
def test_自动接入排队失败不改变成功采集状态(monkeypatch):
batch = SimpleNamespace(requested_by=None, source_database="test_source", sync_mode="FULL", status="RUNNING")
session = SimpleNamespace(rollback=lambda: None)
failures = []
schedule_failures = []
monkeypatch.setattr(worker.task_service, "get_settings", lambda: object())
monkeypatch.setattr(worker, "resolve_tplus_settings", lambda _: SimpleNamespace(t_plus_database="test_source"))
monkeypatch.setattr(worker.task_service, "fail_batch", lambda *args: failures.append(args))
class SyncService:
def __init__(self, source, target):
pass
def execute_claimed(self, task):
task.status = "SUCCEEDED"
def fail_schedule(session):
raise RuntimeError("排队失败")
monkeypatch.setattr(worker, "TPlusSyncService", SyncService)
monkeypatch.setattr(business_sync_control, "schedule", fail_schedule)
monkeypatch.setattr(business_sync_control, "record_schedule_failure", lambda session, source: schedule_failures.append(source))
worker._execute(session, batch, lambda: nullcontext(object()))
assert batch.status == "SUCCEEDED"
assert failures == []
assert schedule_failures == ["test_source"]
@pytest.mark.parametrize("race", ["same", "different", "unrelated"])
def test_业务接入排队完整性错误只核对一次既有任务(monkeypatch, race):
found = SimpleNamespace(kind="BUSINESS_SYNC", requested_by=1, source_database="test_source",
input_json={"start_date": "2026-03-01"})
if race == "different":
found.requested_by = 2
results = iter([None, found if race != "unrelated" else None])
rollbacks = []
class Session:
def get(self, *_args):
return object()
def scalar(self, _query):
return next(results)
def begin_nested(self):
return nullcontext()
def add(self, _row):
pass
def flush(self):
raise IntegrityError("insert", {}, Exception())
def rollback(self):
rollbacks.append(True)
monkeypatch.setattr(business_sync_control, "require_permission", lambda *_args: None)
monkeypatch.setattr(business_sync_control, "history_source_database", lambda _session: "test_source")
monkeypatch.setattr(business_sync_control, "work_out", lambda row: row)
args = (Session(), 1, date(2026, 3, 1), "same-key")
if race == "same":
assert business_sync_control.queue(*args) is found
else:
with pytest.raises(BadRequestError if race == "different" else ConflictError):
business_sync_control.queue(*args)
assert rollbacks == [True]