new feature: Integration with kbdb Autonomous
This commit is contained in:
172
tests/migration/test_requested_tools_parity_pente_fino.py
Normal file
172
tests/migration/test_requested_tools_parity_pente_fino.py
Normal file
@@ -0,0 +1,172 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
import yaml
|
||||
|
||||
from app.domain.contas.service import ContasDomainService
|
||||
from app.domain.contas.workflow_actions import build_contas_workflow_actions
|
||||
from contas_mcp.servers.contas_mcp_server import main as mcp
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
REQUESTED = {
|
||||
"consultar_faturas", "consultar_plano", "invoice_explanation", "buscar_informacao",
|
||||
"consultar_vas", "consultar_historico_vas", "cancelar_vas_avulso",
|
||||
"tratar_vas_estrategico", "validar_contestacao", "contestar_cobranca",
|
||||
"finalizar_atendimento", "consultar_status_solicitacao", "enviar_sms",
|
||||
"recuperar_fatura_pdf", "pro_rata", "termino_desconto", "valor_divergente",
|
||||
"retomar_workflow",
|
||||
}
|
||||
|
||||
|
||||
def test_todas_as_capabilities_solicitadas_estao_expostas_no_mcp():
|
||||
assert REQUESTED <= set(mcp.TOOLS)
|
||||
|
||||
|
||||
def test_todas_as_capabilities_solicitadas_estao_habilitadas_no_registry():
|
||||
cfg = yaml.safe_load((ROOT / "config/tools.yaml").read_text(encoding="utf-8"))["tools"]
|
||||
assert REQUESTED <= set(cfg)
|
||||
assert all(cfg[name].get("enabled", True) for name in REQUESTED)
|
||||
|
||||
|
||||
def test_buscar_informacao_preserva_tool_original_mas_delega_rag_ao_framework():
|
||||
out = ContasDomainService().buscar_informacao(
|
||||
queries=["Aya Audiobooks Premium o que é", "Food Balance o que é"]
|
||||
)
|
||||
assert out["requires_rag"] is True
|
||||
assert out["source"] == "agent_framework.rag"
|
||||
assert out["rag_queries"] == ["Aya Audiobooks Premium o que é", "Food Balance o que é"]
|
||||
|
||||
|
||||
def test_consultar_plano_extrai_planos_da_evidencia_sem_llm():
|
||||
billing = json.loads((ROOT / "app/domain/contas/fixtures/divergencia.json").read_text(encoding="utf-8"))
|
||||
out = ContasDomainService().consultar_plano(msisdn="119", billing_analysis=billing)
|
||||
assert out["count"] == 2
|
||||
assert {p["name"] for p in out["plans"]} == {"TIM Black A 8.0", "TIM CTRL Redes Sociais 8.0"}
|
||||
|
||||
|
||||
def test_invoice_explanation_preserva_detail_e_resumo_semantico_para_composicao():
|
||||
svc = ContasDomainService()
|
||||
detail = {"parsed_content": {"total_geral": 197.43}}
|
||||
out = svc.invoice_explanation(
|
||||
msisdn="119",
|
||||
complete_invoices_payload={"paymentItems": []},
|
||||
billing_analysis={"invoiceExplanation": "Base"},
|
||||
invoice_detail=detail,
|
||||
invoice_amount="197.43",
|
||||
invoice_period="14/10 a 13/11",
|
||||
)
|
||||
assert out["invoice_detail"] == detail
|
||||
assert out["invoice_amount"] == "197.43"
|
||||
assert out["invoice_period"] == "14/10 a 13/11"
|
||||
|
||||
|
||||
def test_invoice_explanation_restaura_composicao_llm_no_framework():
|
||||
reg = build_contas_workflow_actions(ContasDomainService())
|
||||
out = reg.get("formatar_invoice_explanation")(
|
||||
{"explicacao_base": "TIM Fashion R$ 10,00", "invoice_detail": {}}, {"input": {}}
|
||||
)
|
||||
assert out["await_user_input"] is True
|
||||
assert out["requires_llm_composition"] is True
|
||||
assert "não invente" in out["response_instruction"]
|
||||
assert "Com essa explicação, sanei sua dúvida?" in out["mensagem"]
|
||||
|
||||
|
||||
def test_pro_rata_deriva_exatamente_dois_planos_do_pdf_sem_llm():
|
||||
detail = json.loads((ROOT / "app/domain/contas/fixtures/invoice_pdf_include_danfe_true.json").read_text(encoding="utf-8"))
|
||||
args = {"msisdn": "11999999999", "invoice_detail": detail}
|
||||
plans = mcp._derive_pro_rata_plans(args)
|
||||
assert len(plans) == 2
|
||||
assert {p["desc"] for p in plans} == {"TIM Black A 8.0", "TIM CTRL Redes Sociais 8.0"}
|
||||
assert mcp._prepare_pro_rata(args) is None
|
||||
assert args["has_plano_controle"] is True
|
||||
|
||||
|
||||
def test_pro_rata_falha_fechado_sem_exatamente_dois_planos():
|
||||
args = {"msisdn": "119", "planos": [{"desc": "Plano único"}]}
|
||||
out = mcp._prepare_pro_rata(args)
|
||||
assert out["success"] is False
|
||||
assert out["reason"] == "requires_exactly_two_plans"
|
||||
assert out["plans_found"] == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validar_contestacao_usa_mesma_cval_e_rejeita_valor_acima_da_fatura(monkeypatch):
|
||||
billing = json.loads((ROOT / "app/domain/contas/fixtures/divergencia.json").read_text(encoding="utf-8"))
|
||||
|
||||
async def no_enrich(name, args):
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(mcp, "_enrich_invoice_context", no_enrich)
|
||||
out = await mcp._validate_contestation({
|
||||
"msisdn": "11999999999",
|
||||
"subject": "TIM Fashion Mensal",
|
||||
"valor": 150,
|
||||
"motivo": "quero contestar TIM Fashion Mensal",
|
||||
"billing_analysis": billing,
|
||||
})
|
||||
assert out["eligible"] is False
|
||||
assert out["reason"] == "CVAL"
|
||||
assert out["validation_log"][0]["erro"] == "valor_ajuste_maior_que_item"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_validar_contestacao_aprova_quando_item_e_valor_sao_comprovados(monkeypatch):
|
||||
billing = json.loads((ROOT / "app/domain/contas/fixtures/divergencia.json").read_text(encoding="utf-8"))
|
||||
|
||||
async def no_enrich(name, args):
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(mcp, "_enrich_invoice_context", no_enrich)
|
||||
out = await mcp._validate_contestation({
|
||||
"msisdn": "11999999999",
|
||||
"subject": "TIM Fashion Mensal",
|
||||
"valor": 50,
|
||||
"motivo": "quero contestar TIM Fashion Mensal",
|
||||
"billing_analysis": billing,
|
||||
})
|
||||
assert out["eligible"] is True
|
||||
assert out["status"] == "ELIGIBLE"
|
||||
|
||||
|
||||
def test_termino_desconto_e_valor_divergente_preservam_semantica_do_original():
|
||||
reg = build_contas_workflow_actions(ContasDomainService())
|
||||
action = reg.get("formatar_capability_resposta")
|
||||
end = action({"tipo": "termino_desconto", "nome_plano": "TIM Black", "msisdn": "11999999999"}, {"input": {}})
|
||||
div = action({"tipo": "valor_divergente", "msisdn": "11999999999"}, {"input": {}})
|
||||
assert "desconto de fidelidade do plano TIM Black" in end["mensagem"]
|
||||
assert "período promocional contratado expirou" in end["mensagem"]
|
||||
assert "alteração no valor do plano" in div["mensagem"]
|
||||
assert "final 99" in div["mensagem"]
|
||||
|
||||
|
||||
def test_status_solicitacao_nao_confunde_message_id_com_protocolo():
|
||||
mapping = yaml.safe_load((ROOT / "config/mcp_parameter_mapping.yaml").read_text(encoding="utf-8"))["mcp_parameter_mapping"]["tools"]["consultar_status_solicitacao"]
|
||||
assert "interaction_key" not in mapping.get("map", {})
|
||||
assert "protocol" in mapping.get("extract", {})
|
||||
|
||||
|
||||
def test_finalizacao_preserva_status_explicito_do_contrato_original():
|
||||
cfg = yaml.safe_load((ROOT / "config/tools.yaml").read_text(encoding="utf-8"))["tools"]["finalizar_atendimento"]
|
||||
assert "status" in cfg.get("requires", [])
|
||||
mapping = yaml.safe_load((ROOT / "config/mcp_parameter_mapping.yaml").read_text(encoding="utf-8"))["mcp_parameter_mapping"]["tools"]["finalizar_atendimento"]
|
||||
assert "status" in mapping.get("extract", {})
|
||||
|
||||
|
||||
class _DirectClient:
|
||||
def consultar_vas(self, msisdn): return {"products": [{"name": "VAS"}]}
|
||||
def historico_vas(self, msisdn): return {"services": [{"name": "OLD"}]}
|
||||
def status_sr(self, payload): return {"protocolNumber": payload.get("protocolNumber"), "status": "Fechado"}
|
||||
def sms(self, msisdn, message): return {"sent": True, "msisdn": msisdn, "message": message}
|
||||
def secure_pdf(self, msisdn, invoice_id, customer_id=""): return {"invoiceId": invoice_id, "url": "secure"}
|
||||
|
||||
|
||||
def test_tools_diretas_vas_historico_status_sms_pdf_mantem_contratos_de_dominio():
|
||||
svc = ContasDomainService(client=_DirectClient()) # type: ignore[arg-type]
|
||||
assert svc.consultar_vas(msisdn="119")["products"][0]["name"] == "VAS"
|
||||
assert svc.consultar_historico_vas(msisdn="119")["services"][0]["name"] == "OLD"
|
||||
assert svc.consultar_status_solicitacao(msisdn="119", protocol="P1")["protocolNumber"] == "P1"
|
||||
assert svc.enviar_sms(msisdn="119", message="ok")["sent"] is True
|
||||
assert svc.recuperar_fatura_pdf(msisdn="119", invoice_id="I1")["invoiceId"] == "I1"
|
||||
Reference in New Issue
Block a user