"""Regression: relationship sync resolves owner/holder persons via a BATCHED ``str(id) -> person`` map (one query per source) instead of a per-row ``db.get`` — the nightly full sync used to issue thousands of serial round-trips. A broken map key (str vs uuid / hyphenation drift) would drop the edge entirely via the ``if person is None: continue`` guard, so asserting the edge IS emitted with the correct person *label* (which is read off the mapped person) is sufficient to prove the batch path is equivalent to the old ``db.get``. """ from __future__ import annotations import uuid from datetime import UTC, datetime import pytest from app.domains.asset.models import AssetItem from app.domains.relationships.constants import ( REL_ASSIGNED_TO, REL_MANAGES, REL_REPORTS_TO, SOURCE_ASSET, SOURCE_IDENTITY, ) from app.domains.relationships.sync_service import ( RelationshipSyncService, _EdgeBatch, ) from app.identity.person_models import IdentityPerson def _person(**kw) -> IdentityPerson: return IdentityPerson( id=kw.pop("id", uuid.uuid4()), work_email=kw.pop("work_email", f"{uuid.uuid4().hex[:8]}@test.com"), display_name=kw.pop("display_name", "Test Person"), employment_status="active", source_system="successfactors", hris_person_id=kw.pop("hris_person_id", f"sf-{uuid.uuid4().hex[:8]}"), **kw, ) @pytest.mark.asyncio async def test_sync_identity_resolves_manager_via_batched_map(db_session): mgr = _person(display_name="Boss Person") rep = _person(display_name="Report Person", manager_person_id=mgr.id) db_session.add_all([mgr, rep]) await db_session.flush() svc = RelationshipSyncService(db_session) batch = _EdgeBatch(SOURCE_IDENTITY, db_session, datetime.now(UTC)) await svc._sync_identity(batch) manages = [ e for e in batch._buffer if e["rel_type"] == REL_MANAGES and e["from_id"] == str(mgr.id) and e["to_id"] == str(rep.id) ] reports = [ e for e in batch._buffer if e["rel_type"] == REL_REPORTS_TO and e["from_id"] == str(rep.id) and e["to_id"] == str(mgr.id) ] assert len(manages) == 1, "manager edge missing — batched map lookup failed" # Labels are read off the mapped manager/report — proves the map hit. assert manages[0]["from_label"] == "Boss Person" assert manages[0]["to_label"] == "Report Person" assert len(reports) == 1 @pytest.mark.asyncio async def test_sync_assets_resolves_holder_via_batched_map(db_session): holder = _person(display_name="Holder Person") db_session.add(holder) await db_session.flush() asset = AssetItem( id=uuid.uuid4(), asset_tag=f"AT-{uuid.uuid4().hex[:6]}", asset_name="Test laptop", category="laptop", status="claimed", assigned_to=holder.id, assigned_at=datetime.now(UTC), ) db_session.add(asset) await db_session.flush() svc = RelationshipSyncService(db_session) batch = _EdgeBatch(SOURCE_ASSET, db_session, datetime.now(UTC)) await svc._sync_assets(batch) edges = [ e for e in batch._buffer if e["rel_type"] == REL_ASSIGNED_TO and e["from_id"] == str(asset.id) and e["to_id"] == str(holder.id) ] assert len(edges) == 1, "asset-holder edge missing — batched map lookup failed" assert edges[0]["to_label"] == "Holder Person"