Files
clientflow_backend/tests/test_opportunity_next_action_bulk.py

108 lines
4.0 KiB
Python

from contextlib import nullcontext
import pytest
import app.document_reconciliation_service as document_service
import app.operation_service as operation_service
import app.opportunity_next_action_service as service
from app.domain.opportunity_flow import build_opportunity_evidence
class _Result:
def __init__(self, rows):
self._rows = rows
def mappings(self):
return self
def all(self):
return self._rows
class _Connection:
def __init__(self, opportunities, *, tasks=None, operation_links=None):
self.opportunities = opportunities
self.tasks = tasks or []
self.operation_links = operation_links or []
self.query_count = 0
def execute(self, statement, params=None):
self.query_count += 1
sql = str(statement)
if "FROM opportunities WHERE" in sql:
wanted = set((params or {}).get("opportunity_ids", []))
return _Result([row for oid, row in self.opportunities.items() if oid in wanted])
if "FROM tasks WHERE" in sql:
return _Result(self.tasks)
if "FROM operation_links WHERE" in sql:
return _Result(self.operation_links)
return _Result([])
class _Engine:
def __init__(self, connection):
self.connection = connection
def begin(self):
return nullcontext(self.connection)
def _opportunity(oid):
return {
"id": oid,
"stage": "NEW_LEAD",
"status": "open",
"title": "Teste",
"fiscal_customer_id": None,
"customer_id": None,
"metadata": {},
}
@pytest.mark.parametrize("tasks,operation_links", [
([], []),
([{"id": "task-1", "opportunity_id": "11111111-1111-1111-1111-111111111111",
"action_code": "CONTACT_CUSTOMER", "action": "Contactar cliente", "note": "",
"priority": "alta", "route": "/tasks/task-1", "status": "pending",
"due_at": None, "created_at": None, "metadata": {}, "rn": 1}], []),
([], [{"id": "link-1", "opportunity_id": "11111111-1111-1111-1111-111111111111",
"system": "clientflow", "external_type": "payment", "external_id": None,
"external_name": "Pagamento", "external_url": None, "status": "confirmed",
"payload": {}, "last_synced_at": None, "created_at": None, "updated_at": None}]),
])
def test_bulk_decision_is_equivalent_to_individual(monkeypatch, tasks, operation_links):
oid = "11111111-1111-1111-1111-111111111111"
row = _opportunity(oid)
connection = _Connection({oid: row}, tasks=tasks, operation_links=operation_links)
monkeypatch.setattr(service, "engine", _Engine(connection))
monkeypatch.setattr(operation_service, "ensure_operation_schema", lambda: None)
monkeypatch.setattr(document_service, "document_reconciliation_v2_available", lambda conn=None: False)
snapshots = service._bulk_operation_snapshots([oid], {oid: operation_links}, {oid: []})
evidence = build_opportunity_evidence(
row, linked_documents=[], tasks=tasks, operation_snapshot=snapshots[oid],
linked_customer=None, fiscal_data_complete=False,
has_reconciliation_candidate=False, company_profile="blif",
)
monkeypatch.setattr(service, "_build_db_evidence", lambda opportunity_id: evidence)
assert service.get_opportunity_next_actions([oid])[oid] == service.get_opportunity_next_action(oid)
def test_bulk_query_count_is_constant_for_batch_size(monkeypatch):
monkeypatch.setattr(operation_service, "ensure_operation_schema", lambda: None)
monkeypatch.setattr(document_service, "document_reconciliation_v2_available", lambda conn=None: False)
def measured(size):
opportunities = {
f"00000000-0000-0000-0000-{number:012d}":
_opportunity(f"00000000-0000-0000-0000-{number:012d}")
for number in range(1, size + 1)
}
connection = _Connection(opportunities)
monkeypatch.setattr(service, "engine", _Engine(connection))
service.get_opportunity_next_actions(opportunities)
return connection.query_count
assert measured(1) == measured(50) == 6