"""Tests for personnel_number feature (agent-07).""" import asyncio import pytest from httpx import AsyncClient pytestmark = pytest.mark.asyncio USERS_URL = "/api/v1/users" INVITE_URL = "/api/v1/users/invite" COMPANIES_URL = "/api/v1/companies" NEXT_URL = "/api/v1/users/next-personnel-number" def auth(tokens): return {"Authorization": f"Bearer {tokens['access_token']}"} # ── Format-Validierung ─────────────────────────────────────────────────────── async def test_invite_with_letters_in_personnel_number_rejected(client: AsyncClient, registered_user): resp = await client.post(INVITE_URL, headers=auth(registered_user["tokens"]), json={ "email": "letter@test.de", "first_name": "L", "last_name": "L", "personnel_number": "ABC123", }) assert resp.status_code == 422 async def test_invite_with_numeric_personnel_number_ok(client: AsyncClient, registered_user): resp = await client.post(INVITE_URL, headers=auth(registered_user["tokens"]), json={ "email": "num1@test.de", "first_name": "N", "last_name": "N", "personnel_number": "1001", }) assert resp.status_code == 201 assert resp.json()["personnel_number"] == "1001" # ── Eindeutigkeit + Reservierung ───────────────────────────────────────────── async def test_duplicate_personnel_number_rejected(client: AsyncClient, registered_user): h = auth(registered_user["tokens"]) r1 = await client.post(INVITE_URL, headers=h, json={ "email": "dup1@test.de", "first_name": "D", "last_name": "1", "personnel_number": "2001", }) assert r1.status_code == 201 r2 = await client.post(INVITE_URL, headers=h, json={ "email": "dup2@test.de", "first_name": "D", "last_name": "2", "personnel_number": "2001", }) assert r2.status_code == 409 async def test_personnel_number_reserved_after_deactivation(client: AsyncClient, registered_user): h = auth(registered_user["tokens"]) # User mit Nummer anlegen r = await client.post(INVITE_URL, headers=h, json={ "email": "reserve@test.de", "first_name": "R", "last_name": "R", "personnel_number": "3001", }) user_id = r.json()["id"] # Deaktivieren await client.patch(f"{USERS_URL}/{user_id}", headers=h, json={"is_active": False}) # Andere User darf 3001 nicht bekommen r2 = await client.post(INVITE_URL, headers=h, json={ "email": "other@test.de", "first_name": "O", "last_name": "O", "personnel_number": "3001", }) assert r2.status_code == 409 # ── Auto-Vergabe & Counter ─────────────────────────────────────────────────── async def test_next_personnel_number_endpoint(client: AsyncClient, registered_user): r = await client.get(NEXT_URL, headers=auth(registered_user["tokens"])) assert r.status_code == 200 assert r.json()["next"].isdigit() async def test_auto_mode_assigns_personnel_number(client: AsyncClient, registered_user): h = auth(registered_user["tokens"]) # Modus auf auto setzen upd = await client.patch(f"{COMPANIES_URL}/me", headers=h, json={ "personnel_number_mode": "auto", }) assert upd.status_code == 200 # Invite ohne explizite Nr. r = await client.post(INVITE_URL, headers=h, json={ "email": "auto@test.de", "first_name": "A", "last_name": "A", }) assert r.status_code == 201 nr = r.json()["personnel_number"] assert nr is not None and nr.isdigit() # zurück auf manual await client.patch(f"{COMPANIES_URL}/me", headers=h, json={ "personnel_number_mode": "manual", }) async def test_required_flag_blocks_invite_without_number(client: AsyncClient, registered_user): h = auth(registered_user["tokens"]) upd = await client.patch(f"{COMPANIES_URL}/me", headers=h, json={ "personnel_number_required": True, }) assert upd.status_code == 200 try: r = await client.post(INVITE_URL, headers=h, json={ "email": "noreq2@test.de", "first_name": "X", "last_name": "X", }) assert r.status_code == 400 finally: await client.patch(f"{COMPANIES_URL}/me", headers=h, json={ "personnel_number_required": False, }) # ── Lookup ─────────────────────────────────────────────────────────────────── async def test_get_by_personnel_number(client: AsyncClient, registered_user): h = auth(registered_user["tokens"]) r = await client.post(INVITE_URL, headers=h, json={ "email": "lookup@test.de", "first_name": "L", "last_name": "U", "personnel_number": "4001", }) assert r.status_code == 201 g = await client.get(f"{USERS_URL}/by-personnel/4001", headers=h) assert g.status_code == 200 assert g.json()["email"] == "lookup@test.de" nf = await client.get(f"{USERS_URL}/by-personnel/9999999", headers=h) assert nf.status_code == 404