"""Regression: the new-hire onboarding IT-info email is dispatched at most once per hire. Two paths fire ``send_onboarding_it_info`` for the same person: ``HrSyncService.confirm_batch`` (immediately, when the hire is confirmed on/after their start date) and the daily ``hr_lifecycle.hire_day`` cron. For a hire confirmed ON their start date both run the same calendar day. Consolidation (2026-06-29): the former thin ``welcome`` email + the ``hire_day_it_info`` email are now ONE email, deduped across both paths by ``identity_persons.it_info_sent_at``. This test pins that guard. (NOT the credential email — the Google first-login password ships separately to the personal email from account_provisioner.) """ from __future__ import annotations import uuid import pytest from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from app.core.coordinators.hr_sync_coordinator import send_onboarding_it_info from app.identity.person_models import IdentityPerson from app.notifications.models import NotificationOutbox @pytest.mark.asyncio async def test_onboarding_it_info_dispatched_at_most_once( db_session: AsyncSession, ): hris_id = "sf-itinfo-once" person = IdentityPerson( id=uuid.uuid4(), work_email="newhire@x.com", display_name="New Hire", employment_status="active", source_system="successfactors", hris_person_id=hris_id, ) db_session.add(person) await db_session.commit() async def _outbox_count() -> int: return await db_session.scalar( select(func.count(NotificationOutbox.id)).where( NotificationOutbox.recipient_person_id == person.id, NotificationOutbox.template_key == "hire_day_it_info", ) ) # First path fires → dispatches + stamps it_info_sent_at. await send_onboarding_it_info(db_session, hris_id) after_first = await _outbox_count() assert after_first >= 1, "first call should dispatch the onboarding email" assert person.it_info_sent_at is not None, "it_info_sent_at must be stamped" # Second path the same day → must be a no-op (deduped by it_info_sent_at). await send_onboarding_it_info(db_session, hris_id) after_second = await _outbox_count() assert after_second == after_first, ( "onboarding IT-info email must be sent exactly once across both " f"paths; outbox rows grew {after_first} → {after_second}" )