bugfix: route stickness precedences (transaction in the same intent)
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
72
tests/migration/test_mcp_contestation_subject_guard.py
Normal file
72
tests/migration/test_mcp_contestation_subject_guard.py
Normal file
@@ -0,0 +1,72 @@
|
||||
from contas_mcp.servers.contas_mcp_server.main import (
|
||||
_preflight_subject,
|
||||
_recover_explicit_contestation_subject,
|
||||
)
|
||||
|
||||
|
||||
def _args(subject="TIM Fashion Mensal"):
|
||||
return {
|
||||
"msisdn": "11999999999",
|
||||
"subject": subject,
|
||||
"motivo": "não contratei TIM CTRL Redes Sociais 8.0",
|
||||
"valor": 71.99,
|
||||
"billing_analysis": {
|
||||
"currentInvoice": [
|
||||
{
|
||||
"type": "plano",
|
||||
"desc": "Plano",
|
||||
"items": [
|
||||
{"type": "plano", "desc": "TIM Black A 8.0", "value": "104.99", "contestable": False},
|
||||
{"type": "plano", "desc": "TIM CTRL Redes Sociais 8.0", "value": "71.99", "contestable": False},
|
||||
],
|
||||
},
|
||||
{
|
||||
"type": "servicos_contratados_de_parceiros",
|
||||
"desc": "Serviços de valor adicionado",
|
||||
"items": [
|
||||
{"type": "servicos_contratados_de_parceiros", "desc": "TIM Fashion Mensal", "value": "10.0", "contestable": True},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
"invoice_detail": {
|
||||
"parsed_content": {
|
||||
"1199999999": {
|
||||
"Planos": {
|
||||
"TIM CTRL Redes Sociais 8.0": {"valor_final": 71.99}
|
||||
},
|
||||
"SVA Detalhe Total": [
|
||||
{"desc": "Tim Fashion", "value": 10, "classe": "avulso"}
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_recovers_explicit_contestation_subject_from_original_text():
|
||||
item = _recover_explicit_contestation_subject(_args())
|
||||
assert item is not None
|
||||
assert item["name"] == "TIM CTRL Redes Sociais 8.0"
|
||||
assert str(item["value"]) == "71.99"
|
||||
assert item["category"] == "plano"
|
||||
|
||||
|
||||
def test_preflight_does_not_replace_explicit_plan_with_vas():
|
||||
args = _args()
|
||||
result = _preflight_subject("contestar_cobranca", args)
|
||||
assert result is not None
|
||||
assert result["status"] == "OUT_OF_SCOPE"
|
||||
assert result["subject"] == "TIM CTRL Redes Sociais 8.0"
|
||||
assert result["resolved_value"] == "71.99"
|
||||
assert result["metadata"]["subject_corrected_from"] == "TIM Fashion Mensal"
|
||||
assert args["subject"] == "TIM CTRL Redes Sociais 8.0"
|
||||
assert args["resolved_value"] == "71.99"
|
||||
|
||||
|
||||
def test_correct_subject_is_preserved():
|
||||
args = _args(subject="TIM CTRL Redes Sociais 8.0")
|
||||
result = _preflight_subject("contestar_cobranca", args)
|
||||
assert result is not None
|
||||
assert result["subject"] == "TIM CTRL Redes Sociais 8.0"
|
||||
assert args.get("_subject_corrected_from") is None
|
||||
@@ -446,3 +446,79 @@ def test_contestation_action_calculates_totals_only_for_items_actually_contested
|
||||
assert [x["itemName"] for x in result["not_contested_items"]] == ["Outro VAS"]
|
||||
assert result["contested_invoice_amount_open"] == "14.99"
|
||||
assert result["contested_invoice_amount"] == "14.99"
|
||||
|
||||
|
||||
def test_validate_contestation_items_reconhece_vas_por_type_do_billing_analysis() -> None:
|
||||
items = [
|
||||
{
|
||||
"item_name": "TIM Fashion Mensal",
|
||||
"claimed_amount": "10",
|
||||
"validated_amount": "10",
|
||||
}
|
||||
]
|
||||
invoice = {
|
||||
"currentInvoice": [
|
||||
{
|
||||
"type": "servicos_contratados_de_parceiros",
|
||||
"desc": "Serviços de valor adicionado",
|
||||
"value": "76.98",
|
||||
"items": [
|
||||
{
|
||||
"type": "servicos_contratados_de_parceiros",
|
||||
"desc": "TIM Fashion Mensal",
|
||||
"value": "10.0",
|
||||
"contestable": True,
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
validated, validation_log, error = validate_contestation_items(items, invoice)
|
||||
|
||||
assert error is None
|
||||
assert validation_log[-1]["status"] == "aprovado"
|
||||
assert validation_log[-1]["secao_vas"] is True
|
||||
assert validation_log[-1]["item_fatura_resolvido"] == "TIM Fashion Mensal"
|
||||
assert validation_log[-1]["tipo_fatura"] == "servicos_contratados_de_parceiros"
|
||||
assert validated[0]["validated_amount"] == "10"
|
||||
|
||||
|
||||
def test_validate_contestation_items_prefere_evidencia_vas_quando_item_aparece_em_multiplas_visoes() -> None:
|
||||
items = [
|
||||
{
|
||||
"item_name": "TIM Fashion Mensal",
|
||||
"claimed_amount": "10",
|
||||
"validated_amount": "10",
|
||||
}
|
||||
]
|
||||
invoice = {
|
||||
"invoiceVariation": [
|
||||
{
|
||||
"desc": "TIM Fashion Mensal",
|
||||
"value": "10.0",
|
||||
}
|
||||
],
|
||||
"currentInvoice": [
|
||||
{
|
||||
"type": "servicos_contratados_de_parceiros",
|
||||
"desc": "Serviços de valor adicionado",
|
||||
"value": "76.98",
|
||||
"items": [
|
||||
{
|
||||
"type": "servicos_contratados_de_parceiros",
|
||||
"desc": "TIM Fashion Mensal",
|
||||
"value": "10.0",
|
||||
"contestable": True,
|
||||
}
|
||||
],
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
_, validation_log, error = validate_contestation_items(items, invoice)
|
||||
|
||||
assert error is None
|
||||
assert validation_log[-1]["status"] == "aprovado"
|
||||
assert validation_log[-1]["secao_vas"] is True
|
||||
assert validation_log[-1]["tipo_fatura"] == "servicos_contratados_de_parceiros"
|
||||
|
||||
24
tests/migration/test_vas_response_renderer.py
Normal file
24
tests/migration/test_vas_response_renderer.py
Normal file
@@ -0,0 +1,24 @@
|
||||
from app.presentation.tool_renderers import render_contas_vas
|
||||
|
||||
|
||||
def test_vas_renderer_includes_available_values():
|
||||
result = {
|
||||
"products": [
|
||||
{"name": "TIM Fashion Mensal", "can": {"cancel": True}, "details": {"valor": "10,00"}},
|
||||
{"name": "Aya Audiobooks Premium", "can": {"cancel": True}, "details": {"valor": "9,99"}},
|
||||
{"name": "Neymar Jr", "can": {"cancel": True}, "details": {"valor": "12,00"}},
|
||||
{"name": "Tamboro Mensal", "can": {"cancel": True}, "details": {"valor": "14,99"}},
|
||||
]
|
||||
}
|
||||
text = render_contas_vas(tool_name="consultar_vas", result=result, state={}, agent_label="VasAgent")
|
||||
assert "TIM Fashion Mensal (avulso): R$ 10,00" in text
|
||||
assert "Aya Audiobooks Premium (avulso): R$ 9,99" in text
|
||||
assert "Neymar Jr (avulso): R$ 12,00" in text
|
||||
assert "Tamboro Mensal (avulso): R$ 14,99" in text
|
||||
|
||||
|
||||
def test_vas_renderer_does_not_invent_missing_value():
|
||||
result = {"products": [{"name": "Sem Preço", "can": {"cancel": True}, "details": {}}]}
|
||||
text = render_contas_vas(tool_name="consultar_vas", result=result, state={}, agent_label="VasAgent")
|
||||
assert "Sem Preço (avulso)" in text
|
||||
assert "R$" not in text
|
||||
Reference in New Issue
Block a user