"""API tests for deal endpoints.""" from __future__ import annotations from decimal import Decimal import pytest from httpx import AsyncClient from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker from app.models.activity import Activity, ActivityType from app.models.deal import Deal, DealStage, DealStatus from tests.api.v1.task_activity_shared import auth_headers, make_token, prepare_scenario @pytest.mark.asyncio async def test_create_deal_endpoint_uses_context_owner( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: scenario = await prepare_scenario(session_factory) token = make_token(scenario.user_id, scenario.user_email) response = await client.post( "/api/v1/deals/", json={ "contact_id": scenario.contact_id, "title": "Upsell Subscription", "amount": 2500.0, "currency": "USD", }, headers=auth_headers(token, scenario), ) assert response.status_code == 201 payload = response.json() assert payload["owner_id"] == scenario.user_id assert payload["organization_id"] == scenario.organization_id assert payload["title"] == "Upsell Subscription" @pytest.mark.asyncio async def test_list_deals_endpoint_filters_by_status( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: scenario = await prepare_scenario(session_factory) token = make_token(scenario.user_id, scenario.user_email) async with session_factory() as session: base_deal = await session.get(Deal, scenario.deal_id) assert base_deal is not None base_deal.status = DealStatus.NEW won_deal = Deal( organization_id=scenario.organization_id, contact_id=scenario.contact_id, owner_id=scenario.user_id, title="Enterprise Upgrade", amount=Decimal("8000"), currency="USD", status=DealStatus.WON, stage=DealStage.CLOSED, ) session.add(won_deal) await session.commit() response = await client.get( "/api/v1/deals/?status=won", headers=auth_headers(token, scenario), ) assert response.status_code == 200 data = response.json() assert len(data) == 1 assert data[0]["title"] == "Enterprise Upgrade" assert data[0]["status"] == DealStatus.WON.value @pytest.mark.asyncio async def test_update_deal_endpoint_updates_stage_and_logs_activity( session_factory: async_sessionmaker[AsyncSession], client: AsyncClient, ) -> None: scenario = await prepare_scenario(session_factory) token = make_token(scenario.user_id, scenario.user_email) response = await client.patch( f"/api/v1/deals/{scenario.deal_id}", json={ "stage": DealStage.PROPOSAL.value, "status": DealStatus.WON.value, "amount": 5000.0, "currency": "USD", }, headers=auth_headers(token, scenario), ) assert response.status_code == 200 body = response.json() assert body["stage"] == DealStage.PROPOSAL.value assert body["status"] == DealStatus.WON.value assert Decimal(body["amount"]) == Decimal("5000") async with session_factory() as session: activity_types = await session.scalars( select(Activity.type).where(Activity.deal_id == scenario.deal_id), ) collected = set(activity_types.all()) assert ActivityType.STAGE_CHANGED in collected assert ActivityType.STATUS_CHANGED in collected