Projeto do Agent Contas ORACLE

This commit is contained in:
2026-08-19 09:35:50 -03:00
commit 950a2bcd33
1366 changed files with 177217 additions and 0 deletions

View File

@@ -0,0 +1,324 @@
from __future__ import annotations
from app.domain.contas.service import ContasDomainService
from app.domain.contas.workflow_actions import build_contas_workflow_actions
class _Client:
def __init__(self, *, protocol="INFO-123", fail=False):
self.protocol = protocol
self.fail = fail
self.protocol_calls = []
self.status_calls = []
def abrir_protocolo(self, payload):
self.protocol_calls.append(dict(payload))
if self.fail:
raise RuntimeError("falha protocolo")
return {"interactionProtocol": self.protocol}
def status_sr(self, payload):
self.status_calls.append(dict(payload)); return {"ok": True}
def _action(client):
service = ContasDomainService(client=client)
reg = build_contas_workflow_actions(service)
return reg.get("finalizar_atendimento_action")
def _codes(result):
return [x["code"] for x in result.get("business_events") or []]
def test_invoice_explanation_finalization_orders_events_and_returns_alias():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "Atendimento concluído.",
"msisdn": "11999999999", "social_sec_no": "123", "message_id": "m1",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Explicação dos valores da fatura.",
}, {"input": {}})
assert result["finalizacao_protocol"] == "INFO-123"
assert _codes(result) == ["CVN.008", "RCT.085", "CVN.010", "MPI.006", "SAD.001"]
def test_invoice_explanation_negative_emits_cvn009_mpi005_without_protocol_when_no_notes():
client = _Client()
result = _action(client)({
"status": "nao_resolvido", "summary": "Cliente não concordou.",
"business_workflows_executed": ["invoice_explanation"],
}, {"input": {}})
assert client.protocol_calls == []
assert _codes(result) == ["CVN.009", "MPI.005", "SAD.001"]
def test_handoff_suppression_emits_only_sad001():
client = _Client()
result = _action(client)({
"status": "nao_resolvido", "summary": "ATH",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Explicação.",
"suppress_cvn_009_on_finalize": True,
"suppress_cvn_lookup_on_finalize": True,
"suppress_informational_protocol_on_finalize": True,
}, {"input": {}})
assert client.protocol_calls == []
assert _codes(result) == ["SAD.001"]
def test_protocol_failure_does_not_fail_finalization_and_emits_negative_events():
client = _Client(fail=True)
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Explicação da fatura.",
}, {"input": {}})
assert result["success"] is True
assert "finalizacao_protocol" not in result
assert _codes(result) == ["CVN.008", "RCT.086", "CVN.011", "MPI.006", "SAD.001"]
def test_transactional_workflow_does_not_emit_informational_acceptance():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "concluído", "protocol_closed": True,
"protocol_number": "PRT-1", "business_workflows_executed": ["contestacao_tool"],
}, {"input": {}})
assert _codes(result) == ["SAD.001"]
def test_sad_decision_tree_handoff_second_time():
client = _Client()
result = _action(client)({
"status": "nao_resolvido", "summary": "ATH",
"sad_exit_decision_enabled": True, "human_handoff": True, "ath_first_time": False,
}, {"input": {}})
assert _codes(result) == ["SAD.001", "SAD.003", "SAD.004", "SAD.006"]
def test_invoice_explanation_uses_canonical_notes_not_free_text():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Resumo qualquer vindo do prefetch e do LLM.",
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"
assert result["finalizacao_protocol"] == "INFO-123"
def test_strategic_partner_is_classified_without_invoice_detail():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"informational_service_names": ["Paramount+ Mensal"],
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Estratégico"
assert result["finalizacao_protocol"] == "INFO-123"
def test_known_avulso_is_classified_without_invoice_detail():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"informational_service_names": ["TIM Fashion Mensal"],
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Avulso"
assert result["finalizacao_protocol"] == "INFO-123"
def test_prefetch_invoice_context_guarantees_lookup_and_rt15_without_latched_workflow():
client = _Client()
result = _action(client)({
"status": "resolvido_outros_assuntos",
"summary": "Encerramento realizado pelo agente.",
"msisdn": "11999999999",
"invoice_id": "3000131181",
"invoice_explanation_base": "Resumo da fatura carregado no prefetch.",
}, {"input": {}})
assert result["finalizacao_protocol"] == "INFO-123"
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"
assert _codes(result) == ["CVN.002", "CVN.006", "CVN.008", "RCT.085", "CVN.010", "MPI.006", "SAD.001"]
def test_unresolved_transition_does_not_reemit_positive_cvn_or_mpi():
client = _Client()
result = _action(client)({
"status": "resolvido",
"summary": "Cliente aceitou no fluxo de negócio.",
"invoice_id": "3000131182",
"conversation_unresolved_transition_emitted": True,
"invoice_explanation_base": "Resumo da fatura.",
}, {"input": {}})
assert _codes(result) == ["SAD.001"]
def test_terminal_veb_resolution_suppresses_cvn_mpi_and_duplicate_rt15():
client = _Client()
result = _action(client)({
"status": "resolvido",
"summary": "Cliente aceitou a explicação.",
"protocol_number": "VEB-123",
"protocol_closed": True,
"conversation_explanation_resolved": True,
"suppress_cvn_protocol_ic": True,
"informational_vas_types": ["bundle"],
"informational_service_names": ["Pacote Europa Promocional"],
}, {"input": {}})
assert client.protocol_calls == []
assert result["protocol_number"] == "VEB-123"
assert _codes(result) == ["SAD.001"]
def test_invoice_detail_conflict_overrides_saved_informational_type():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"informational_service_names": ["TIM Fashion Mensal"],
"informational_vas_types": ["bundle"],
"invoice_detail": {"119": {"SVA Detalhe Total": [{"desc": "TIM Fashion Mensal", "value": 19.9, "classe": "avulso"}]}},
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Avulso"
assert result["finalizacao_protocol"] == "INFO-123"
def test_invoice_detail_without_match_ignores_saved_type_and_does_not_create_protocol():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"informational_service_names": ["Serviço que não consta"],
"informational_vas_types": ["bundle"],
"invoice_detail": {"119": {"Serviços Bundle Inclusos": [{"desc": "Outro serviço", "value": 0}]}},
}, {"input": {}})
assert client.protocol_calls == []
assert "finalizacao_protocol" not in result
def test_rag_saved_type_is_used_when_invoice_detail_is_absent():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "ok", "msisdn": "119",
"informational_service_names": ["Serviço explicado pelo RAG"],
"informational_rag_vas_types": ["bundle"],
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle"
assert result["finalizacao_protocol"] == "INFO-123"
def test_partial_invoice_inference_merges_saved_avulso_type():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "Cliente entendeu a explicação e agradeceu.", "msisdn": "119",
"informational_service_names": ["Pacote Europa Promocional", "YouTube Premium Mensal", "Aluguel de Filme 3"],
"informational_vas_types": ["avulso"],
"invoice_detail": {"119": {
"Serviços Bundle Inclusos": [{"desc": "Pacote Europa Promocional", "value": 0}],
"Serviços Contratados de Terceiros": [{"desc": "YouTube Premium Mensal", "value": 24.9, "classe": "estrategico"}],
}},
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico, VAS Avulso"
assert result["finalizacao_protocol"] == "INFO-123"
def test_existing_session_protocol_prevents_duplicate_informational_rt15():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "Cliente entendeu a explicação.",
"customer_protocols": [{"number": "PRT-EXISTENTE"}],
"informational_service_names": ["Paramount+ Mensal"],
}, {"input": {}})
assert client.protocol_calls == []
assert "finalizacao_protocol" not in result
def test_cpf_alias_is_forwarded_to_informational_protocol():
client = _Client()
_action(client)({
"status": "resolvido", "summary": "Cliente entendeu a explicação.",
"msisdn": "11999999999", "cpf": "12345678901",
"informational_service_names": ["Paramount+ Mensal"],
}, {"input": {}})
assert client.protocol_calls[0]["socialSecNo"] == "12345678901"
def test_three_informational_vas_types_have_canonical_order():
client = _Client()
_action(client)({
"status": "resolvido", "summary": "Cliente entendeu.", "msisdn": "119",
"informational_vas_types": ["avulso", "bundle", "estrategico"],
}, {"input": {}})
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico, VAS Avulso"
def test_free_customer_phrase_without_evidence_does_not_create_protocol():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "Cliente entendeu a explicação.",
"customer_message": "o que é incluído no plano, mas está sendo cobrado?",
}, {"input": {}})
assert client.protocol_calls == []
assert "finalizacao_protocol" not in result
def test_legacy_final_alias_normalizes_to_resolved_without_spurious_protocol():
client = _Client()
result = _action(client)({"status": "final", "summary": ""}, {"input": {}})
assert result["status"] == "resolvido"
assert client.protocol_calls == []
def test_transactional_cancel_finalization_does_not_emit_cvn_or_mpi_even_with_summary():
client = _Client()
result = _action(client)({
"status": "resolvido", "summary": "Cancelamento concluído.",
"business_workflows_executed": ["cancelamento_vas_avulso"],
"protocol_number": "CAN-123", "protocol_closed": True,
}, {"input": {}})
assert _codes(result) == ["SAD.001"]
def test_strategic_notes_take_priority_over_prior_invoice_explanation_notes():
client = _Client()
result = _action(client)({
"status": "resolvido",
"summary": "Cliente entendeu a explicação e agradeceu.",
"msisdn": "11999999999",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Explicação dos valores da fatura.",
"informational_service_names": ["YouTube Premium Mensal"],
"informational_vas_types": ["estrategico"],
}, {"input": {}})
assert result["finalizacao_protocol"] == "INFO-123"
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Estratégico"
def test_deferred_bundle_and_strategic_items_create_combined_rt15_without_workflow_latch():
client = _Client()
result = _action(client)({
"status": "resolvido",
"summary": "Cliente entendeu a explicação e agradeceu.",
"msisdn": "11999999999",
"protocol_deferred_to_finalization": True,
"informational_service_names": ["Pacote Europa Promocional", "YouTube Premium Mensal"],
"informational_vas_types": ["bundle", "estrategico"],
"invoice_detail": {
"11999999999": {
"Serviços Bundle Inclusos": [{"desc": "Pacote Europa Promocional", "value": 0}],
"Serviços Contratados de Terceiros": [{"desc": "YouTube Premium Mensal", "value": 24.9, "classe": "estrategico"}],
}
},
}, {"input": {}})
assert result["finalizacao_protocol"] == "INFO-123"
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação de VAS Bundle, VAS Estratégico"
def test_invoice_explanation_only_registers_protocol_at_finalization():
client = _Client()
result = _action(client)({
"status": "resolvido",
"summary": "Cliente aceitou a explicação.",
"msisdn": "11999999999",
"business_workflows_executed": ["invoice_explanation"],
"invoice_explanation_base": "Explicação dos valores da fatura.",
}, {"input": {}})
assert len(client.protocol_calls) == 1
assert result["finalizacao_protocol"] == "INFO-123"
assert client.protocol_calls[0]["serviceRequestNotes"] == "Explicação dos valores da fatura"