from inspect import getsource import app.admin_dashboard as dashboard import app.admin_ui.pages.opportunities as page import app.commercial_service as commercial import app.integration_outbox_service as outbox import app.jasmin_backfill_service as backfill import app.operation_service as operation def test_detail_context_loads_reusable_groups_once(monkeypatch): calls = {} def once(name, value): def load(*args, **kwargs): calls[name] = calls.get(name, 0) + 1 return value return load opportunity = {"id": "opp", "local_customer_id": "customer", "status": "open", "stage": "NEW_LEAD"} monkeypatch.setattr(page, "get_opportunity", once("opportunity", opportunity)) monkeypatch.setattr(page, "list_opportunity_tasks", once("tasks", [])) monkeypatch.setattr(page, "list_opportunity_events", once("events", [])) monkeypatch.setattr(page, "list_opportunity_items", once("items", [])) monkeypatch.setattr(page, "list_products", once("products", [])) monkeypatch.setattr(page, "list_communications_for_opportunity", once("communications", [])) monkeypatch.setattr(page, "_opportunity_odoo_rows", once("odoo_candidates", ([], []))) monkeypatch.setattr(commercial, "get_customer_for_opportunity", once("customer", {"id": "customer"})) monkeypatch.setattr(commercial, "list_commercial_documents", once("documents", [])) monkeypatch.setattr(operation, "get_operation_links", once("operation_links", [])) monkeypatch.setattr(operation, "get_operation_snapshot", once("operation_snapshot", {"cards": [], "links": []})) monkeypatch.setattr(outbox, "list_outbox", once("outbox", [])) monkeypatch.setattr(backfill, "find_jasmin_document_candidates_for_opportunity", once("jasmin_candidates", [])) context = page.load_opportunity_detail_context("opp") assert context is not None assert calls == { "opportunity": 1, "tasks": 1, "events": 1, "items": 1, "products": 1, "communications": 1, "odoo_candidates": 1, "customer": 1, "documents": 1, "operation_links": 1, "operation_snapshot": 1, "outbox": 1, "jasmin_candidates": 1, } def test_products_panel_preloaded_render_matches_standalone(monkeypatch): items = [{"id": "i1", "product_name": "Produto", "quantity": 1, "unit_price": 10, "total_price": 10, "status": "ACTIVE", "jasmin_sales_item": "A1", "metadata": {}}] products = [{"id": "p1", "sku": "SKU", "jasmin_sales_item": "A1", "name": "Produto"}] monkeypatch.setattr(dashboard, "list_opportunity_items", lambda opportunity_id: items) monkeypatch.setattr(dashboard, "list_products", lambda **kwargs: products) standalone = dashboard.opportunity_products_panel_html("opp") preloaded = dashboard.opportunity_products_panel_html( "opp", preloaded_items=items, preloaded_products=products, ) assert preloaded == standalone def test_detail_route_threads_context_into_repeated_panels(): source = getsource(page.opportunity_detail_page) assert "load_opportunity_detail_context(opportunity_id)" in source assert "preloaded_documents=context.resolved_documents" in source assert "preloaded_items=context.opportunity_items" in source assert "preloaded_products=context.active_products" in source assert "preloaded_candidates=context.odoo_candidates" in source assert "preloaded_items=context.outbox_items" in source assert "preloaded=context.next_action_preloaded()" in source def test_detail_read_path_contains_no_schema_initialization_or_ddl(): readers = ( page.load_opportunity_detail_context, commercial.get_customer_for_opportunity, commercial.list_commercial_documents, commercial.list_customers, operation.get_operation_links, ) forbidden = ("ensure_", "CREATE TABLE", "CREATE INDEX", "ALTER TABLE") for reader in readers: source = getsource(reader) for token in forbidden: assert token not in source, (reader.__name__, token) route_source = getsource(page.opportunity_detail_page) assert "ensure_pending_task_for_next_action" not in route_source assert "materialized_task" not in route_source def test_context_next_action_customer_aliases_preserve_evidence_contract(): context = page.OpportunityDetailContext( opportunity_id="opp", opportunity={"id": "opp", "local_customer_id": "customer"}, customer={"id": "customer", "email": "a@b.pt", "street_name": "Rua", "postal_zone": "1000-001", "city_name": "Lisboa"}, ) customer = context.next_action_preloaded()["customer"] assert customer["billing_email"] == "a@b.pt" assert customer["address"] == "Rua" assert customer["postal_code"] == "1000-001" assert customer["city"] == "Lisboa"