132 lines
5.2 KiB
Python
132 lines
5.2 KiB
Python
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
|
|
|
|
|
|
def test_cancel_preflight_exact_plan_is_out_of_scope_and_never_rebound_to_vas():
|
|
args = _args(subject="TIM CTRL Redes Sociais 8.0")
|
|
result = _preflight_subject("cancelar_vas_avulso", args)
|
|
assert result is not None
|
|
assert result["status"] == "OUT_OF_SCOPE"
|
|
assert args["subject"] == "TIM CTRL Redes Sociais 8.0"
|
|
assert "TIM Fashion" not in str(result)
|
|
|
|
|
|
def test_invoice_resolver_exact_plan_identity_wins_before_similarity_matcher():
|
|
from app.domain.contas.invoice_resolver import InvoiceResolver
|
|
from app.domain.contas.item_matcher import SimilarityItemMatcher
|
|
|
|
detail = _args(subject="TIM CTRL Redes Sociais 8.0")["billing_analysis"]
|
|
outcome = InvoiceResolver(matcher=SimilarityItemMatcher()).resolve(
|
|
["TIM CTRL Redes Sociais 8.0"], detail
|
|
)
|
|
assert outcome.resolved == []
|
|
assert len(outcome.out_of_scope) == 1
|
|
assert outcome.out_of_scope[0].matches[0].canonical_name == "TIM CTRL Redes Sociais 8.0"
|
|
|
|
|
|
def test_recovers_explicit_subject_from_runtime_query_fields_without_motivo():
|
|
args = _args(subject="TIM CTRL Redes Sociais")
|
|
args.pop("motivo", None)
|
|
args["query"] = "nao contratei TIM CTRL Redes Sociais 8.0"
|
|
args["operator_instructions"] = "nao contratei TIM CTRL Redes Sociais 8.0"
|
|
args["valor"] = 8
|
|
|
|
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"
|
|
|
|
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 CTRL Redes Sociais"
|
|
assert args["subject"] == "TIM CTRL Redes Sociais 8.0"
|
|
assert args["resolved_value"] == "71.99"
|
|
|
|
|
|
def test_all_supported_original_text_fields_recover_explicit_subject():
|
|
for field in ("query", "operator_instructions", "message", "text", "motivo", "descricao"):
|
|
args = _args(subject="TIM CTRL Redes Sociais")
|
|
for candidate in ("query", "operator_instructions", "message", "text", "motivo", "descricao"):
|
|
args.pop(candidate, None)
|
|
args[field] = "nao contratei TIM CTRL Redes Sociais 8.0"
|
|
args["valor"] = 8
|
|
|
|
item = _recover_explicit_contestation_subject(args)
|
|
assert item is not None, field
|
|
assert item["name"] == "TIM CTRL Redes Sociais 8.0", field
|
|
assert str(item["value"]) == "71.99", field
|