@ -9,6 +9,7 @@ from fastapi import HTTPException
from app . services . flows . order_flow import OrderFlowMixin
from app . services . flows . order_flow import OrderFlowMixin
from app . services . flows . review_flow import ReviewFlowMixin
from app . services . flows . review_flow import ReviewFlowMixin
from app . integrations . telegram_satellite_service import _ensure_supported_runtime_configuration
from app . services . orchestration . conversation_policy import ConversationPolicy
from app . services . orchestration . conversation_policy import ConversationPolicy
from app . services . orchestration . entity_normalizer import EntityNormalizer
from app . services . orchestration . entity_normalizer import EntityNormalizer
from app . services . tools . handlers import _parse_data_hora_revisao
from app . services . tools . handlers import _parse_data_hora_revisao
@ -202,6 +203,21 @@ class ReviewFlowHarness(ReviewFlowMixin):
class ConversationAdjustmentsTests ( unittest . TestCase ) :
class ConversationAdjustmentsTests ( unittest . TestCase ) :
def test_telegram_satellite_requires_redis_in_production ( self ) :
with patch ( " app.integrations.telegram_satellite_service.settings.environment " , " production " ) , patch (
" app.integrations.telegram_satellite_service.settings.conversation_state_backend " ,
" memory " ,
) :
with self . assertRaises ( RuntimeError ) :
_ensure_supported_runtime_configuration ( )
def test_telegram_satellite_allows_redis_in_production ( self ) :
with patch ( " app.integrations.telegram_satellite_service.settings.environment " , " production " ) , patch (
" app.integrations.telegram_satellite_service.settings.conversation_state_backend " ,
" redis " ,
) :
_ensure_supported_runtime_configuration ( )
def test_defer_flow_cancel_when_order_cancel_draft_waits_for_reason ( self ) :
def test_defer_flow_cancel_when_order_cancel_draft_waits_for_reason ( self ) :
state = FakeState (
state = FakeState (
entries = {
entries = {
@ -361,6 +377,77 @@ class CreateOrderFlowWithVehicleTests(unittest.IsolatedAsyncioTestCase):
self . assertIn ( " Encontrei 2 veiculo(s): " , response )
self . assertIn ( " Encontrei 2 veiculo(s): " , response )
self . assertIn ( " Honda Civic 2021 " , response )
self . assertIn ( " Honda Civic 2021 " , response )
async def test_order_flow_extracts_budget_from_message_when_llm_misses_it ( self ) :
state = FakeState (
contexts = {
10 : {
" generic_memory " : { } ,
" shared_memory " : { } ,
" last_stock_results " : [ ] ,
" selected_vehicle " : None ,
}
}
)
registry = FakeRegistry ( )
flow = OrderFlowHarness ( state = state , registry = registry )
async def fake_hydrate_mock_customer_from_cpf ( cpf : str , user_id : int | None = None ) :
return { " cpf " : cpf , " user_id " : user_id }
with patch (
" app.services.flows.order_flow.hydrate_mock_customer_from_cpf " ,
new = fake_hydrate_mock_customer_from_cpf ,
) :
response = await flow . _try_collect_and_create_order (
message = " Quero comprar um carro de 50 mil, meu CPF e 12345678909 " ,
user_id = 10 ,
extracted_fields = { } ,
intents = { } ,
turn_decision = { " intent " : " order_create " , " domain " : " sales " , " action " : " collect_order_create " } ,
)
self . assertIn ( " Encontrei 2 veiculo(s): " , response )
self . assertEqual ( state . get_user_context ( 10 ) [ " generic_memory " ] [ " orcamento_max " ] , 50000 )
async def test_order_flow_extracts_cpf_from_followup_message_when_llm_misses_it ( self ) :
state = FakeState (
entries = {
" pending_order_drafts " : {
10 : {
" payload " : { } ,
" expires_at " : datetime . utcnow ( ) + timedelta ( minutes = 30 ) ,
}
}
} ,
contexts = {
10 : {
" generic_memory " : { " orcamento_max " : 50000 } ,
" shared_memory " : { " orcamento_max " : 50000 } ,
" last_stock_results " : [ ] ,
" selected_vehicle " : None ,
}
} ,
)
registry = FakeRegistry ( )
flow = OrderFlowHarness ( state = state , registry = registry )
async def fake_hydrate_mock_customer_from_cpf ( cpf : str , user_id : int | None = None ) :
return { " cpf " : cpf , " user_id " : user_id }
with patch (
" app.services.flows.order_flow.hydrate_mock_customer_from_cpf " ,
new = fake_hydrate_mock_customer_from_cpf ,
) :
response = await flow . _try_collect_and_create_order (
message = " Meu CPF e 12345678909 " ,
user_id = 10 ,
extracted_fields = { } ,
intents = { } ,
)
self . assertIn ( " Encontrei 2 veiculo(s): " , response )
self . assertEqual ( registry . calls [ 0 ] [ 0 ] , " consultar_estoque " )
async def test_order_flow_lists_stock_from_budget_when_vehicle_is_missing ( self ) :
async def test_order_flow_lists_stock_from_budget_when_vehicle_is_missing ( self ) :
state = FakeState (
state = FakeState (
entries = {
entries = {