fix: decouple org preference and ai model preferences

This commit is contained in:
Abhishek Kumar 2026-06-09 15:40:34 +05:30
parent e26d902425
commit 01d898fc72
21 changed files with 460 additions and 238 deletions

View file

@ -1,3 +1,4 @@
from types import SimpleNamespace
from unittest.mock import AsyncMock, MagicMock, patch
from fastapi import FastAPI
@ -14,14 +15,14 @@ from api.services.configuration.registry import (
)
def _make_test_app():
def _make_test_app(selected_organization_id=None):
app = FastAPI()
app.include_router(router)
mock_user = MagicMock()
mock_user.id = 1
mock_user.is_superuser = False
mock_user.selected_organization_id = None
mock_user.selected_organization_id = selected_organization_id
app.dependency_overrides[get_user] = lambda: mock_user
return app
@ -210,3 +211,38 @@ class TestMaskedKeyRejection:
)
assert response.status_code == 200
def test_preference_only_update_does_not_validate_or_save_model_config(self):
"""Saving a test phone number through the legacy endpoint must not touch models."""
app = _make_test_app(selected_organization_id=11)
client = TestClient(app)
preferences = SimpleNamespace(test_phone_number=None, timezone=None)
with (
patch("api.routes.user.db_client") as mock_db,
patch("api.routes.user.UserConfigurationValidator") as mock_validator,
patch(
"api.routes.user.get_organization_preferences",
new=AsyncMock(return_value=preferences),
),
patch(
"api.routes.user.upsert_organization_preferences",
new=AsyncMock(return_value=preferences),
) as upsert_preferences,
):
existing = _existing_openai_config()
mock_db.get_user_configurations = AsyncMock(return_value=existing)
mock_db.update_user_configuration = AsyncMock()
mock_db.get_organization_by_id = AsyncMock(return_value=None)
mock_validator.return_value.validate = AsyncMock()
response = client.put(
"/user/configurations/user",
json={"test_phone_number": "+15551234567"},
)
assert response.status_code == 200
assert response.json()["test_phone_number"] == "+15551234567"
mock_db.update_user_configuration.assert_not_called()
mock_validator.return_value.validate.assert_not_called()
upsert_preferences.assert_awaited_once()

View file

@ -103,6 +103,61 @@ def test_initiate_call_executes_as_workflow_owner_for_shared_org_workflow():
assert initiate_kwargs["workflow_id"] == workflow.id
assert initiate_kwargs["user_id"] == workflow.user_id
assert "user_id=99" in initiate_kwargs["webhook_url"]
mock_db.get_user_configurations.assert_not_called()
def test_initiate_call_uses_organization_preference_phone_number():
app = _make_test_app()
client = TestClient(app)
workflow = _workflow()
provider = _provider()
quota_mock = AsyncMock(
return_value=SimpleNamespace(has_quota=True, error_message="")
)
with (
patch("api.routes.telephony.db_client") as mock_db,
patch(
"api.routes.telephony.check_dograh_quota_by_user_id",
new=quota_mock,
),
patch(
"api.routes.telephony.get_default_telephony_provider",
new=AsyncMock(return_value=provider),
),
patch(
"api.routes.telephony.get_backend_endpoints",
new=AsyncMock(return_value=("https://api.example.com", "wss://ignored")),
),
):
mock_db.get_user_configurations = AsyncMock(
return_value=SimpleNamespace(test_phone_number="+15550000000")
)
mock_db.get_configuration = Mock(
return_value=SimpleNamespace(value={"test_phone_number": "+15557654321"})
)
mock_db.get_default_telephony_configuration = AsyncMock(
return_value=SimpleNamespace(id=55)
)
mock_db.get_workflow = AsyncMock(return_value=workflow)
mock_db.create_workflow_run = AsyncMock(
return_value=SimpleNamespace(
id=501,
name="WR-TEL-OUT-00000001",
initial_context={},
)
)
mock_db.update_workflow_run = AsyncMock()
response = client.post(
"/telephony/initiate-call",
json={"workflow_id": workflow.id},
)
assert response.status_code == 200
assert provider.initiate_call.await_args.kwargs["to_number"] == "+15557654321"
mock_db.get_user_configurations.assert_not_called()
def test_initiate_call_rejects_existing_run_for_different_workflow():