from __future__ import annotations from importlib import import_module from unittest.mock import patch from sqlalchemy import create_engine, text from govoplan_campaign.backend.campaign.models import BuildStatus, SendStatus from govoplan_campaign.backend.messages.models import ImapStatus, MessageDraft, MessageValidationStatus from govoplan_campaign.backend.persistence.campaigns import _job_from_message def test_excluded_message_persists_explicit_skipped_transport_states() -> None: message = MessageDraft( entry_index=0, entry_id="excluded-entry", active=True, build_status=BuildStatus.BUILT, validation_status=MessageValidationStatus.EXCLUDED, send_status=SendStatus.SKIPPED, imap_status=ImapStatus.SKIPPED, ) job = _job_from_message( tenant_id="tenant-1", campaign_id="campaign-1", version_id="version-1", message=message, ) assert job.send_status == "skipped" assert job.imap_status == "skipped" def test_status_migration_only_normalizes_excluded_rows_without_transport_evidence() -> None: migration = import_module( "govoplan_campaign.backend.migrations.versions." "d8b3e2c1f4a5_v0110_excluded_delivery_skipped" ) engine = create_engine("sqlite+pysqlite:///:memory:") with engine.begin() as connection: connection.execute(text( "CREATE TABLE campaign_jobs (" "id TEXT PRIMARY KEY, validation_status TEXT NOT NULL, " "send_status TEXT NOT NULL, imap_status TEXT NOT NULL)" )) connection.execute( text( "INSERT INTO campaign_jobs (id, validation_status, send_status, imap_status) VALUES " "('untouched', 'excluded', 'not_queued', 'pending'), " "('evidence', 'excluded', 'smtp_accepted', 'appended'), " "('queueable', 'ready', 'not_queued', 'pending')" ) ) with patch.object(migration.op, "get_bind", return_value=connection): migration.upgrade() rows = { row.id: (row.send_status, row.imap_status) for row in connection.execute( text("SELECT id, send_status, imap_status FROM campaign_jobs ORDER BY id") ) } assert rows["untouched"] == ("skipped", "skipped") assert rows["evidence"] == ("smtp_accepted", "appended") assert rows["queueable"] == ("not_queued", "pending")