"""来源单价确认接口的权限边界。""" from unittest.mock import Mock import pytest from app.api.v1.business.businesses import confirm_guidance, confirm_source_price from app.core.exceptions import ForbiddenError from app.schemas.business_source import GuidanceConfirmIn, SourcePriceConfirmIn from app.services import authorization_service, business_source from app.services.authorization_policy import permission_for def test_来源单价确认路由要求业务更新权限(): assert permission_for("business.businesses", "confirm_source_price", "PUT") == "business:businesses:update" def test_无核算准备权限不能确认来源单价(monkeypatch): session, actor, meta = Mock(), Mock(), Mock() confirm = Mock() def deny(current_session, current_actor, permission): assert (current_session, current_actor, permission) == (session, actor, "payroll:prepare") raise ForbiddenError("无权核算准备") monkeypatch.setattr(authorization_service, "require_permission", deny) monkeypatch.setattr(business_source, "confirm_missing_source_price", confirm) payload = SourcePriceConfirmIn(revision="0" * 64, evidence="核对原单") with pytest.raises(ForbiddenError): confirm_source_price(session, actor, 1, 1, payload, meta) confirm.assert_not_called() def test_指导成本登记必须同时具备核算准备和事实维护权限(monkeypatch): session, actor, meta = Mock(), Mock(), Mock() save = Mock(return_value={"status": "CREATED"}) permissions = [] def allow(current_session, current_actor, permission): assert (current_session, current_actor) == (session, actor) permissions.append(permission) monkeypatch.setattr(authorization_service, "require_permission", allow) monkeypatch.setattr(business_source, "confirm_guidance", save) payload = GuidanceConfirmIn(shipment_item_id=1, amount="2.1234", evidence="核对月度指导成本") result = confirm_guidance(session, actor, 1, payload, meta) assert result.data == {"status": "CREATED"} assert permissions == ["payroll:prepare", "tplus:facts"] save.assert_called_once_with(session, 1, payload, actor, meta) def test_缺事实维护权限不能登记指导成本(monkeypatch): session, actor, meta = Mock(), Mock(), Mock() save = Mock() def deny(current_session, current_actor, permission): if permission == "tplus:facts": raise ForbiddenError("无权维护事实") monkeypatch.setattr(authorization_service, "require_permission", deny) monkeypatch.setattr(business_source, "confirm_guidance", save) payload = GuidanceConfirmIn(shipment_item_id=1, amount="2", evidence="核对") with pytest.raises(ForbiddenError): confirm_guidance(session, actor, 1, payload, meta) save.assert_not_called() @pytest.mark.parametrize("amount", ["abc", "-1", "1.12345", "NaN"]) def test_指导成本入参拒绝非法精度和值(amount): with pytest.raises(ValueError): GuidanceConfirmIn(shipment_item_id=1, amount=amount, evidence="核对")