Projeto do Agent Contas ORACLE
This commit is contained in:
266
tests/migration/test_tim_event_metadata_parity.py
Normal file
266
tests/migration/test_tim_event_metadata_parity.py
Normal file
@@ -0,0 +1,266 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
from agent_framework.analytics.tim_payload_mapper import map_analytics_event_to_tim_flat_payload
|
||||
from app.domain.contas.workflow_actions import build_contas_workflow_actions
|
||||
|
||||
|
||||
def _event(result: dict, code: str) -> dict:
|
||||
return next(x for x in result.get("business_events", []) if x.get("code") == code)
|
||||
|
||||
|
||||
def test_contestacao_vaa_metadata_preserva_contexto_tim_original():
|
||||
class Client:
|
||||
def billing_analysis(self, msisdn):
|
||||
return {"currentInvoice": [{"desc": "Serviços de valor adicionado", "items": [{"desc": "VAS Musica", "value": 29.9, "classe": "avulso"}]}]}
|
||||
|
||||
def contestar(self, payload):
|
||||
return {"barcode": "8469", "itemsResponse": []}
|
||||
|
||||
class Service:
|
||||
client = Client()
|
||||
|
||||
action = build_contas_workflow_actions(Service()).get("abrir_contestacao_cliente")
|
||||
state = {
|
||||
"input": {
|
||||
"session_id": "sess-1",
|
||||
"message_id": "msg-1",
|
||||
"ura_call_id": "CALL-123",
|
||||
"channel_id": "URA",
|
||||
}
|
||||
}
|
||||
result = action(
|
||||
{
|
||||
"msisdn": "11999998888",
|
||||
"protocolo_id": "PRT-11",
|
||||
"invoice_id": "3000135012",
|
||||
"servico": "VAS Musica",
|
||||
"valor": 29.9,
|
||||
},
|
||||
state,
|
||||
)
|
||||
payload = _event(result, "VAA.006")["payload"]
|
||||
assert payload["agentId"] == "contas"
|
||||
assert payload["channelId"] == "URA"
|
||||
assert payload["gsm"] == "11999998888"
|
||||
assert payload["uraCallId"] == "CALL-123"
|
||||
assert payload["sessionId"] == "sess-1"
|
||||
assert payload["messageId"] == "msg-1"
|
||||
assert payload["agentProtocolId"] == "PRT-11"
|
||||
assert payload["adjustedProtocol"] == "PRT-11"
|
||||
assert payload["billingId"] == "3000135012"
|
||||
assert payload["adjustedItems"] == ["VAS Musica"]
|
||||
assert payload["adjustedItemsAmount"] == ["29.9"]
|
||||
assert json.loads(payload["agentSpecificData"]) == {
|
||||
"adjustedItems": ["VAS Musica"],
|
||||
"adjustedItemsAmount": ["29.9"],
|
||||
}
|
||||
|
||||
|
||||
def test_contestacao_vaa007_falha_preserva_protocolo_e_itens():
|
||||
class Client:
|
||||
def billing_analysis(self, msisdn):
|
||||
return {"currentInvoice": [{"desc": "Serviços de valor adicionado", "items": [{"desc": "VAS Musica", "value": 29.9, "classe": "avulso"}]}]}
|
||||
|
||||
def contestar(self, payload):
|
||||
raise RuntimeError("falha provider")
|
||||
|
||||
class Service:
|
||||
client = Client()
|
||||
|
||||
action = build_contas_workflow_actions(Service()).get("abrir_contestacao_cliente")
|
||||
result = action(
|
||||
{"msisdn": "119", "protocolo_id": "PRT-11", "invoice_id": "INV-1", "servico": "VAS Musica", "valor": 29.9},
|
||||
{"input": {"channel_id": "URA", "ura_call_id": "CALL-1"}},
|
||||
)
|
||||
payload = _event(result, "VAA.007")["payload"]
|
||||
assert payload["agentProtocolId"] == "PRT-11"
|
||||
assert payload["adjustedProtocol"] == "PRT-11"
|
||||
assert payload["adjustedItems"] == ["VAS Musica"]
|
||||
assert payload["adjustedItemsAmount"] == ["29.9"]
|
||||
|
||||
|
||||
def test_tim_payload_mapper_aceita_agent_specific_data_json_string_historico():
|
||||
mapped = map_analytics_event_to_tim_flat_payload(
|
||||
"VAA.006",
|
||||
{
|
||||
"eventType": "VAA.006",
|
||||
"payload": {
|
||||
"tag": "VAA.006",
|
||||
"agentProtocolId": "P1",
|
||||
"agentSpecificData": '{"billingId":"3000131180","item":"VAS"}',
|
||||
},
|
||||
},
|
||||
)
|
||||
assert mapped["agentProtocolId"] == "P1"
|
||||
assert mapped["agentSpecificData"] == {"billingId": "3000131180", "item": "VAS"}
|
||||
|
||||
|
||||
def test_finalizacao_cvn010_preserva_protocolos_e_contexto_ura():
|
||||
from app.domain.contas.service import ContasDomainService
|
||||
|
||||
class Client:
|
||||
def abrir_protocolo(self, payload):
|
||||
return {"interactionProtocol": "INFO-123"}
|
||||
def status_sr(self, payload):
|
||||
return {"ok": True}
|
||||
|
||||
action = build_contas_workflow_actions(ContasDomainService(client=Client())).get("finalizar_atendimento_action")
|
||||
result = action(
|
||||
{
|
||||
"status": "resolvido",
|
||||
"summary": "ok",
|
||||
"msisdn": "11999999999",
|
||||
"social_sec_no": "123",
|
||||
"session_id": "sess-final",
|
||||
"message_id": "msg-final",
|
||||
"ura_call_id": "CALL-FINAL",
|
||||
"ura_protocol_id": "URA-123",
|
||||
"channel_id": "URA",
|
||||
"invoice_id": "3000131180",
|
||||
"business_workflows_executed": ["invoice_explanation"],
|
||||
"invoice_explanation_base": "Explicação.",
|
||||
},
|
||||
{"input": {}},
|
||||
)
|
||||
payload = _event(result, "CVN.010")["payload"]
|
||||
assert payload["agentProtocolId"] == "INFO-123"
|
||||
assert payload["adjustedProtocol"] == "INFO-123"
|
||||
assert payload["uraProtocolId"] == "URA-123"
|
||||
assert payload["uraCallId"] == "CALL-FINAL"
|
||||
assert payload["channelId"] == "URA"
|
||||
assert payload["billingId"] == "3000131180"
|
||||
assert json.loads(payload["agentSpecificData"]) == {"billingId": "3000131180"}
|
||||
|
||||
|
||||
def test_vas_estrategico_veb_preserva_turno_e_contexto_ura():
|
||||
class Client:
|
||||
def abrir_protocolo(self, payload):
|
||||
return {"interactionProtocol": "VEB-123"}
|
||||
|
||||
class Service:
|
||||
client = Client()
|
||||
|
||||
action = build_contas_workflow_actions(Service()).get("registrar_atendimento_vas_estrategico")
|
||||
result = action(
|
||||
{
|
||||
"linhas": [{"msisdn": "5511999999999"}],
|
||||
"mensagem_base": "Informação sobre cancelamento.",
|
||||
},
|
||||
{
|
||||
"input": {
|
||||
"resposta_usuario": "NAO",
|
||||
"customer_message": "Não quero manter o serviço.",
|
||||
"ura_call_id": "155344608",
|
||||
"channel_id": "ura",
|
||||
"message_id": "msg-005",
|
||||
}
|
||||
},
|
||||
)
|
||||
codes = [x["code"] for x in result["business_events"]]
|
||||
assert codes == ["VEB.004", "VEB.006", "VEB.007"]
|
||||
payload = _event(result, "VEB.004")["payload"]
|
||||
assert payload["uraCallId"] == "155344608"
|
||||
assert payload["channelId"] == "ura"
|
||||
assert payload["messageId"] == "msg-005"
|
||||
assert payload["customerMessage"] == "NAO"
|
||||
assert payload["llmResponse"] == "Informação sobre cancelamento."
|
||||
|
||||
|
||||
def test_finalizacao_mpi006_e_sad001_preservam_metadata_conversacional():
|
||||
from app.domain.contas.service import ContasDomainService
|
||||
|
||||
class Client:
|
||||
def abrir_protocolo(self, payload):
|
||||
return {"interactionProtocol": "INFO-321"}
|
||||
def status_sr(self, payload):
|
||||
return {"ok": True}
|
||||
|
||||
action = build_contas_workflow_actions(ContasDomainService(client=Client())).get("finalizar_atendimento_action")
|
||||
result = action(
|
||||
{
|
||||
"status": "resolvido",
|
||||
"summary": "Cliente entendeu.",
|
||||
"msisdn": "11999999999",
|
||||
"invoice_id": "3000131180",
|
||||
"business_workflows_executed": ["invoice_explanation"],
|
||||
"invoice_explanation_base": "Explicação dos valores da fatura",
|
||||
"customer_message": "Sim, entendi",
|
||||
"llm_response": "Perfeito, fico feliz em ajudar.",
|
||||
"message_id": "msg-final",
|
||||
"session_id": "sess-final",
|
||||
"channel_id": "URA",
|
||||
"ura_call_id": "CALL-FINAL",
|
||||
"session_end_at": "2026-06-11T12:00:00Z",
|
||||
},
|
||||
{"input": {}},
|
||||
)
|
||||
mpi = _event(result, "MPI.006")["payload"]
|
||||
assert mpi["customerMessage"] == "Sim, entendi"
|
||||
assert mpi["llmResponse"] == "Perfeito, fico feliz em ajudar."
|
||||
assert mpi["billingId"] == "3000131180"
|
||||
assert mpi["messageId"] == "msg-final"
|
||||
assert mpi["sessionId"] == "sess-final"
|
||||
|
||||
sad = _event(result, "SAD.001")["payload"]
|
||||
assert sad["llmResponse"] == "Perfeito, fico feliz em ajudar."
|
||||
assert sad["messageId"] == "msg-final"
|
||||
assert sad["sessionEndAt"] == 1781179200000
|
||||
|
||||
|
||||
def test_vas_bundle_nao_defera_protocolo_e_emite_veb005():
|
||||
class Client:
|
||||
def __init__(self): self.calls = 0
|
||||
def abrir_protocolo(self, payload):
|
||||
self.calls += 1
|
||||
return {"interactionProtocol": "SHOULD-NOT-HAPPEN"}
|
||||
|
||||
client = Client()
|
||||
class Service: pass
|
||||
service = Service(); service.client = client
|
||||
action = build_contas_workflow_actions(service).get("registrar_atendimento_vas_estrategico")
|
||||
result = action(
|
||||
{
|
||||
"linhas": [{"msisdn": "5511999999999", "bundle_names": ["TIM Segurança"]}],
|
||||
"mensagem_base": "Bundle incluso no plano.",
|
||||
},
|
||||
{"input": {"resposta_usuario": "NAO", "ura_call_id": "CALL-1", "channel_id": "URA", "message_id": "M1"}},
|
||||
)
|
||||
assert [x["code"] for x in result["business_events"]] == ["VEB.004", "VEB.005", "VEB.007"]
|
||||
assert client.calls == 0
|
||||
assert result["protocol_closed"] is False
|
||||
assert result["protocol_deferred_to_finalization"] is True
|
||||
assert result["suppress_cvn_protocol_ic"] is True
|
||||
assert result["informational_vas_types"] == ["bundle"]
|
||||
|
||||
|
||||
def test_invoice_explanation_mpi005_preserva_turno_e_contexto():
|
||||
class Service: pass
|
||||
action = build_contas_workflow_actions(Service()).get("registrar_atendimento_invoice_explanation")
|
||||
result = action(
|
||||
{"caminho": "NAO", "invoice_id": "INV-9"},
|
||||
{"input": {"customer_message": "Ainda não entendi", "message_id": "M9", "session_id": "S9", "channel_id": "URA", "ura_call_id": "C9"}},
|
||||
)
|
||||
payload = _event(result, "MPI.005")["payload"]
|
||||
assert payload["customerMessage"] == "Ainda não entendi"
|
||||
assert payload["messageId"] == "M9"
|
||||
assert payload["sessionId"] == "S9"
|
||||
assert payload["channelId"] == "URA"
|
||||
assert payload["uraCallId"] == "C9"
|
||||
assert payload["billingId"] == "INV-9"
|
||||
|
||||
|
||||
def test_pro_rata_mpi010_preserva_contexto_do_turno():
|
||||
class Service: pass
|
||||
action = build_contas_workflow_actions(Service()).get("preparar_pro_rata")
|
||||
result = action(
|
||||
{"planos": [], "msisdn": "11999999999"},
|
||||
{"input": {"customer_message": "Por que veio proporcional?", "message_id": "MP1", "session_id": "SP1", "channel_id": "web"}},
|
||||
)
|
||||
payload = _event(result, "MPI.010")["payload"]
|
||||
assert payload["gsm"] == "11999999999"
|
||||
assert payload["customerMessage"] == "Por que veio proporcional?"
|
||||
assert payload["messageId"] == "MP1"
|
||||
assert payload["sessionId"] == "SP1"
|
||||
assert payload["channelId"] == "web"
|
||||
Reference in New Issue
Block a user