from fansifter_common.testing.factories import ModelFactory, SQLAlchemyFactory from fansifter_common.utils import timezone from fansifter_common.utils.uuid import uuid_string from polyfactory import Use from app.enums import CampaignStatus, MessageChannel from app.models import ( AudienceTextFan, BatchRecipient, BatchSendRecord, Campaign, CampaignBatch, ) from app.types import CampaignSendCountry, CampaignSendTimezone class CampaignFactory(SQLAlchemyFactory[Campaign]): id = Use(uuid_string) status = CampaignStatus.SCHEDULED channel = MessageChannel.SMS audience_snapshot_id = Use(lambda: SQLAlchemyFactory.__faker__.uuid4(cast_to=str)) global_participant_id = Use(lambda: SQLAlchemyFactory.__faker__.uuid4(cast_to=str)) content = "Hello world" send_at = Use( lambda: SQLAlchemyFactory.__faker__.future_datetime(tzinfo=timezone.UTC) ) prepared_at = None cancelled_at = None deleted_at = None class CampaignBatchFactory(SQLAlchemyFactory[CampaignBatch]): __set_foreign_keys__ = True campaign_id = Use(uuid_string) country_code = "US" state_province = None batch_offset = 0 first_sent_at = None last_sent_at = None completed_at = None cancelled_at = None created_at = Use(timezone.now) updated_at = Use(timezone.now) class BatchRecipientFactory(SQLAlchemyFactory[BatchRecipient]): __set_foreign_keys__ = True fan_id = Use(uuid_string) fan_phone_number = Use(lambda: SQLAlchemyFactory.__faker__.phone_number()) fan_country = "US" fan_state = None fan_area_code = None class BatchSendRecordFactory(SQLAlchemyFactory[BatchSendRecord]): __set_foreign_keys__ = True id = Use(uuid_string) sent_at = Use(timezone.now) class AudienceTextFanFactory(SQLAlchemyFactory[AudienceTextFan]): audience_id = Use(uuid_string) fan_id = Use(uuid_string) fan_phone_number = Use(lambda: SQLAlchemyFactory.__faker__.phone_number()) fan_country = "US" fan_state = None fan_area_code = None channel = "SMS" class CampaignSendTimezoneFactory(ModelFactory[CampaignSendTimezone]): __model__ = CampaignSendTimezone # Attribute names must match the pydantic field aliases -- the model has # no `populate_by_name`, so overrides only take effect keyed by alias. ianaTzId = "America/New_York" utcOffsetStd = "-5" stateProvinces = ["NY"] quietHoursMin = "09:00:00" quietHoursMax = "20:00:00" nextSafeTime = None isInSafeHours = True isAdjusted = False sendAtLocal = "2026-07-08T10:00:00" class CampaignSendCountryFactory(ModelFactory[CampaignSendCountry]): __model__ = CampaignSendCountry countryCode = "US" timezones = Use(lambda: [CampaignSendTimezoneFactory.build()])