from __future__ import annotations import pytest from agent_framework.idempotency import InMemoryIdempotencyStore from app.domain.contas.client import TimApiClient from app.domain.contas.service import ContasDomainService from app.domain.contas.workflow_actions import build_contas_workflow_actions from app.domain.contas.integrations.secure_pdf_crypto import decrypt_secure_pdf_value def _real_client(monkeypatch): monkeypatch.setenv("TIM_USE_MOCK_GATEWAY", "false") monkeypatch.setenv("TIM_GATEWAY_MODE", "real") return TimApiClient() def test_complete_invoices_preserves_clientid_contract(monkeypatch): client = _real_client(monkeypatch) monkeypatch.setenv("TIM_COMPLETE_INVOICES_URL", "http://tim/complete") calls = [] monkeypatch.setattr(client, "request", lambda *a, **kw: calls.append((a, kw)) or {}) client.consultar_faturas("5511999999999") args, kw = calls[0] assert args[:2] == ("POST", "http://tim/complete") assert kw["payload"] == {"msisdn": "5511999999999"} assert kw["headers"]["ClientID"] == "AIAGENTCR" def test_query_vas_preserves_original_client_id_and_url(monkeypatch): client = _real_client(monkeypatch) monkeypatch.setenv("TIM_URL_CONSULTA_VAS", "http://tim/access/v1/{msisdn}/partnerServices") calls = [] monkeypatch.setattr(client, "request", lambda *a, **kw: calls.append((a, kw)) or {}) client.consultar_vas("5511999999999") args, kw = calls[0] assert args == ("GET", "http://tim/access/v1/5511999999999/partnerServices") assert kw["headers"]["clientId"] == "AIAAGENTCR" def test_bill_pdf_and_secure_pdf_are_distinct_contracts(monkeypatch): client = _real_client(monkeypatch) monkeypatch.setenv("TIM_URL_INVOICE_RECOVER", "http://tim/invoice") calls = [] monkeypatch.setattr(client, "request", lambda *a, **kw: calls.append((a, kw)) or {"parsed_content": {"ok": True}}) detailed = client.bill_pdf("119", "INV-1", "CUS-1") assert detailed["parsed_content"] == {"ok": True} args, kw = calls.pop(0) assert args == ("POST", "http://tim/invoice") assert decrypt_secure_pdf_value(kw["payload"]["invoiceId"]) == "INV-1" assert decrypt_secure_pdf_value(kw["payload"]["customerId"]) == "CUS-1" assert kw["payload"]["invoiceType"] == "DETALHADA" assert kw["headers"]["Accept"] == "application/pdf" client.secure_pdf("119", "INV-1", "CUS-1") args, kw = calls.pop(0) assert args == ("GET", "http://tim/invoice") assert decrypt_secure_pdf_value(kw["params"]["invoiceId"]) == "INV-1" assert decrypt_secure_pdf_value(kw["params"]["msisdn"]) == "119" assert decrypt_secure_pdf_value(kw["params"]["customerId"]) == "CUS-1" def test_line_info_extracts_nested_social_sec_no(monkeypatch): client = _real_client(monkeypatch) monkeypatch.setenv("TIM_PROFILE_FULL_URL", "http://tim/info/{msisdn}") monkeypatch.setattr(client, "request", lambda *a, **kw: {"customer": {"socialSecNo": "12345678900"}}) result = client.line_info("5511999999999") assert result["social_sec_no"] == "12345678900" @pytest.mark.asyncio async def test_cancel_workflow_action_is_idempotent_without_domain_local_cache(monkeypatch): monkeypatch.setenv("TIM_USE_MOCK_GATEWAY", "true") service = ContasDomainService() store = InMemoryIdempotencyStore(namespace="test") registry = build_contas_workflow_actions(service, idempotency_store=store) action = registry.get("cancelamento_vas_avulso_batch") params = { "idempotency_key": "interaction-1", "items": [{"msisdn": "11999999999", "name": "TIM Fashion Mensal"}], } first = await action(params, {"input": {}}) second = await action(params, {"input": {}}) assert first["success"] is True assert second["success"] is True assert second["results"][0]["idempotent_replay"] is True