"""API tests for deal endpoints.""" from __future__ import annotations from decimal import Decimal import pytest from app.models.activity import Activity, ActivityType from app.models.deal import Deal, DealStage, DealStatus from httpx import AsyncClient from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker 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